在Groovy中,如何从嵌套Map中删除属性?

时间:2013-03-12 03:15:53

标签: grails map groovy

我在Grails中编写一个测试,确保来自客户端的传入JSON包含所有必需字段。地图看起来像:

def map = [
    customer: [
        firstName: 'John',
        lastName: 'Doe',
        id: '123',
    ],
    orderNumber: '123456',
    paymentInfo: [
        type: 'paypal',
        amount: '1200',
        currency: 'USD'
    ]
]

换句话说,customerpaymentInfo键是用子键映射的。

在我的测试中,我想删除每个键和子键以确保输入验证正常。我做了这样的事情:

// 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
}

是否可以通过这种方式删除子密钥,如果是,我该怎么做?

1 个答案:

答案 0 :(得分:1)

不幸的是,'customer.firstName'不是顶层地图的关键,因此它不起作用。您可以执行某些操作来解析传入的密钥。

试试这个吗?

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甚至更深,那么像这样的东西应该可以正常工作而没有一堆难以阅读的通用代码。

如果你绝对想要让它适用于任意深度的子地图:

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
}

我注意到你的“地图”没有在两次测试之间恢复......原来的测试也没有这样做,所以我的代码表现相同。