如何在groovy中检索嵌套属性

时间:2011-03-30 15:45:32

标签: groovy properties nested resolver getproperty

我想知道在Groovy中检索嵌套属性的最佳方法是什么,获取给定的Object和任意“property”字符串。我想这样的事情:

someGroovyObject.getProperty("property1.property2")

我很难找到其他人想要这样做的例子,所以也许我不理解一些基本的Groovy概念。似乎必须有一些优雅的方法来做到这一点。

作为参考,Wicket中有一个功能正是我正在寻找的,称为PropertyResolver: http://wicket.apache.org/apidocs/1.4/org/apache/wicket/util/lang/PropertyResolver.html

任何提示都将不胜感激!

4 个答案:

答案 0 :(得分:24)

我不知道Groovy是否有内置的方法来执行此操作,但这里有2个解决方案。在Groovy Console中运行此代码进行测试。

def getProperty(object, String property) {

  property.tokenize('.').inject object, {obj, prop ->       
    obj[prop]
  }  
}

// Define some classes to use in the test
class Name {
  String first
  String second
}

class Person {
  Name name
}

// Create an object to use in the test
Person person = new Person(name: new Name(first: 'Joe', second: 'Bloggs'))

// Run the test
assert 'Joe' == getProperty(person, 'name.first')

/////////////////////////////////////////
// Alternative Implementation
/////////////////////////////////////////
def evalProperty(object, String property) {
  Eval.x(object, 'x.' + property)
}

// Test the alternative implementation
assert 'Bloggs' == evalProperty(person, 'name.second')

答案 1 :(得分:3)

Groovy Beans可让您直接访问字段。您不必定义getter / setter方法。它们是为您生成的。无论何时访问bean属性,都会在内部调用getter / setter方法。您可以使用。@运算符绕过此行为。请参阅以下示例:

class Person {
    String name
    Address address
    List<Account> accounts = []
}

class Address {
    String street
    Integer zip
}

class Account {
    String bankName
    Long balance
}

def person = new Person(name: 'Richardson Heights', address: new Address(street: 'Baker Street', zip: 22222)) 
person.accounts << new Account(bankName: 'BOA', balance: 450)
person.accounts << new Account(bankName: 'CitiBank', balance: 300)

如果您不处理馆藏,只需拨打您想要访问的字段即可。

assert 'Richardson Heights' == person.name
assert 'Baker Street' == person.address.street
assert 22222 == person.address.zip

如果要访问集合中的字段,则必须选择元素:

assert 'BOA' == person.accounts[0].bankName
assert 300 == person.accounts[1].balance​​​​​​​​​

答案 2 :(得分:1)

您也可以使用propertyMissing。这就是你可以称之为Groovy的内置方法。

在你的班级中声明:

def propertyMissing(String name) {
    if (name.contains(".")) {
        def (String propertyname, String subproperty) = name.tokenize(".")
        if (this.hasProperty(propertyname) && this."$propertyname".hasProperty(subproperty)) {
            return this."$propertyname"."$subproperty"
        }
    }
}

然后根据需要参考您的属性:

def properties = "property1.property2"
assert someGroovyObject."$properties" == someValue

这是自动递归的,您不必显式调用方法。这只是一个吸气剂,但您可以定义第二个带参数的版本来制作一个设定器。

缺点是,据我所知,您只能定义propertyMissing的一个版本,因此您必须决定动态路径导航是否是您想要使用的版本。

答案 3 :(得分:0)

https://stackoverflow.com/a/15632027/2015517

它使用$ {}语法,可以用作GString

的一部分