如何在groovy中检索嵌套属性

发布于 2024-10-27 11:57:08 字数 474 浏览 10 评论 0原文

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

someGroovyObject.getProperty("property1.property2")

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

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

任何提示将不胜感激!

I'm wondering what is the best way to retrieve nested properties in Groovy, taking a given Object and arbitrary "property" String. I would like to something like this:

someGroovyObject.getProperty("property1.property2")

I've had a hard time finding an example of others wanting to do this, so maybe I'm not understanding some basic Groovy concept. It seems like there must be some elegant way to do this.

As reference, there is a feature in Wicket that is exactly what I'm looking for, called the PropertyResolver:
http://wicket.apache.org/apidocs/1.4/org/apache/wicket/util/lang/PropertyResolver.html

Any hints would be appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

雨后咖啡店 2024-11-03 11:57:08

我不知道 Groovy 是否有内置的方法来做到这一点,但这里有 2 个解决方案。在 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')

I don't know if Groovy has a built-in way to do this, but here are 2 solutions. Run this code in the Groovy Console to test it.

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')
没企图 2024-11-03 11:57:08

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​​​​​​​​​

Groovy Beans let you access fields directly. You do not have to define getter/setter methods. They get generated for you. Whenever you access a bean property the getter/setter method is called internally. You can bypass this behavior by using the .@ operator. See the following example:

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)

If you are not dealing with collections you can simply just call the field you want to access.

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

If you want to access a field within a collection you have to select the element:

assert 'BOA' == person.accounts[0].bankName
assert 300 == person.accounts[1].balance​​​​​​​​​
伤感在游骋 2024-11-03 11:57:08

您还可以使用 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

这是自动递归的,您不必显式调用方法。这只是一个 getter,但您也可以使用参数定义第二个版本来创建 setter。

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

You can also use propertyMissing. This is what you might call Groovy's built-in method.

Declare this in your class:

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

Then refer to your properties as desired:

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

This is automatically recursive, and you don't have to explicitly call a method. This is only a getter, but you can define a second version with parameters to make a setter as well.

The downside is that, as far as I can tell, you can only define one version of propertyMissing, so you have to decide if dynamic path navigation is what you want to use it for.

凉墨 2024-11-03 11:57:08

请参阅

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

它使用 ${} 语法,可以用作一部分GString 的

See

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

It uses ${} syntax that can be used as part of GString

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文