Принятое решение верное, я просто хочу показать альтернативу, которая делает то же самое немного другим способом, предполагая, что вы хотите придерживаться пунктирной записи для field
в вашем блоке where:
.Я просто добавил еще два тестовых случая, чтобы убедиться, что он работает должным образом.
@Unroll
def "set #field to #value"() {
setup: 'create json'
Map json = [user: [name: 'ABC', address: [street: '21 Main St', zip: '12345', city: 'Hometown']]]
when: 'update it'
def subMap = json
field.split("[.]").each {
if (subMap[it] instanceof Map)
subMap = subMap[it]
else
subMap[it] = value
}
println json
then: 'check the assignment'
json.newField == value ||
json.user.name == value ||
json.user.address.zip == value
where:
field | value
'newField' | 'dummy'
'user.name' | 'XYZ'
'user.address.zip' | '98765'
}
Обновление: Если вы хотите сохранить несколько строк кода, вы также можетеиспользуйте операцию сгиба (или уменьшения или накопления) с помощью inject(..)
, как описано здесь
@Unroll
def "set #field to #value"() {
setup: 'create json'
Map json = [user: [name: 'ABC', address: [street: '21 Main St', zip: '12345', city: 'Hometown']]]
when: 'update it'
field.split("[.]").inject(json) { subMap, key ->
subMap[key] instanceof Map ? subMap[key] : subMap.put(key, value)
}
println json
then: 'check the assignment'
json.newField == value ||
json.user.name == value ||
json.user.address.zip == value
where:
field | value
'newField' | 'dummy'
'user.name' | 'XYZ'
'user.address.zip' | '98765'
}
Считаете ли вы, что это читается или нет, может зависеть от вашего знакомства с такими темами, как функциональное программирование ввообще или карта / уменьшить в частности.Прелесть здесь, в дополнение к краткости, заключается в том, что нам больше не нужна локальная переменная вне нашего замыкания, а мы просто внедряем (отсюда и название метода) результат итерации n в итерацию n + 1.
Кстати, какхороший побочный эффект inject(..)
, поскольку я использую его здесь, возвращает предыдущее значение значения, которое вы установили или перезаписали.Просто добавьте println
перед field.split("[.]").inject(json) ...
, чтобы увидеть его.
Обновление 2: Обратите внимание, что оба варианта работают, только если не существует существующего значения полявведите Map
в поле назначения из-за instanceof Map
проверки эвристики в моем коде.Т.е. эти два случая не будут работать:
'user.address' | [street: '23 Test Blvd', zip: '33333', city: 'Somewhere']
'user.address' | '23 Test Blvd, 33333 Somewhere'
Этот вариант будет работать, хотя, потому что нет никакого ранее существующего значения:
'user.alternativeAddress' | [street: '23 Test Blvd', zip: '33333', city: 'Somewhere']