我正在 Grails 中编写一个测试,以确保从客户端传入的 JSON 包含所有必需的字段。 map 看起来像这样:
def map = [
customer: [
firstName: 'John',
lastName: 'Doe',
id: '123',
],
orderNumber: '123456',
paymentInfo: [
type: 'paypal',
amount: '1200',
currency: 'USD'
]
]
换句话说,customer
和 paymentInfo
键本身就是带有子键的映射。
在我的测试中,我想删除每个键和子键以确保输入验证正常工作。我做了这样的事情:
// test 1
map.remove('orderNumber')
def result = service.performAction(map)
assert result == ServiceCall.ValidationError
// test 2
map.remove('customer.firstName')
def result = service.performAction(map)
assert result == ServiceCall.ValidationError
测试 1 有效并正确删除了 orderNumber
键,但测试 2 没有删除 firstName
子键。我知道我可以使用 map.customer.remove(firstName)
并且它将正确删除子项,但我正在尝试使测试足够通用,以便我只需要传递一个数组字符串及其键和子键将被正确删除,例如:
def array = ['orderNumber', 'customer.firstName', 'customer.lastName', etc...]
array.each {
map.remove(it)
def result = service.performAction(map)
assert result == ServiceCall.ValidationError
}
是否可以通过这种方式删除子项,如果可以,我该怎么做?
最佳答案
不幸的是,“customer.firstName”不是顶级映射的键,因此它不起作用。您可以做一些事情来解析您传入的 key 。
试试这个?
array.each {
def levels = it.tokenize('.')
if ( levels.size() == 1 ) {
map.remove(levels[0])
} else if ( level.size() == 2 ) {
map.get(levels[0]).remove(levels[1])
} // else etc.
def result = service.performAction(map)
assert result == ServiceCall.ValidationError
}
注意,我做了这个非常非通用的深度...您可以轻松编写一个通用函数来删除第 n 级 map 属性。但是,如果您知道只需要 2 甚至 3 层深度,那么类似这样的东西应该可以正常工作,而无需一堆难以阅读的通用代码。
如果您确实想让它适用于任意深度的子 map :
array.each {
def levels = it.tokenize('.')
if ( levels.size() == 1 ) {
map.remove(levels[0])
} else {
def ref = map
levels[0..-2].each {
ref = ref[it]
}
ref.remove(levels[-1])
}
def result = service.performAction(map)
assert result == ServiceCall.ValidationError
}
我确实注意到你的“ map ”在测试之间没有恢复...你原来的测试也没有这样做,所以我的代码行为相同。
关于grails - 在 Groovy 中,如何从嵌套 Map 中删除属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15352658/