如何在groovy中检索嵌套属性

如何在groovy中检索嵌套属性,groovy,properties,nested,resolver,getproperty,Groovy,Properties,Nested,Resolver,Getproperty,我想知道在Groovy中检索嵌套属性的最佳方法是什么,即获取给定对象和任意“属性”字符串。我想这样说: someGroovyObject.getProperty("property1.property2") 我很难找到其他人想要这样做的例子,所以我可能不理解Groovy的一些基本概念。看来一定有什么优雅的方法可以做到这一点 作为参考,Wicket中有一个功能正是我想要的,叫做PropertyResolver: 任何提示都将不胜感激 我不知道Groovy是否有一种内置的方法来实现这一点,但这里

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

someGroovyObject.getProperty("property1.property2")
我很难找到其他人想要这样做的例子,所以我可能不理解Groovy的一些基本概念。看来一定有什么优雅的方法可以做到这一点

作为参考,Wicket中有一个功能正是我想要的,叫做PropertyResolver:


任何提示都将不胜感激

我不知道Groovy是否有一种内置的方法来实现这一点,但这里有两种解决方案。在中运行此代码以测试它

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')
允许您直接访问字段。您不必定义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 'BOA' == person.accounts[0].bankName
assert 300 == person.accounts[1].balance​​​​​​​​​

它使用${}语法,可以用作GString的一部分,您也可以使用它。这就是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
这是自动递归的,您不必显式地调用方法。这只是一个getter,但您也可以使用参数定义第二个版本来创建setter


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

这或多或少是我现在正在做的,但您的方式更干净!对不起,唐,早就应该接受你的回答了(回到我不知道自己在这个网站上做什么的时候)。谢谢…注意:我对这些进行了分类测试,Eval比我系统上的标记化版本慢得多。我建议在getProperty实现中使用null检查。否则,它将在遍历对象图时对null抛出异常。(提交编辑)这是一个很好的建议,但我希望能够接受字符串。有没有办法强迫person.address.street返回person.address.street的值?您可以使用。但是,它要求您声明方法名:person.“getAddress”()​.“getStreet”()​​​​​​​​​​​.谢谢你的信息和链接。。。我会仔细阅读,看看它是否能帮上忙。这里有另一种可能更适合你需要的方法。您可以使用类:Eval.x(person,“x.address.street”)​​​​​​​​​​​​​​​​​.请参阅,您可以使用${}语法动态访问bean的属性。e、 g:person.${propertyName}
def properties = "property1.property2"
assert someGroovyObject."$properties" == someValue