How to get nested properties in groovy

I'm wondering what is the best way to get nested properties in Groovy by taking a given object and an arbitrary β€œproperty” String. I would like something like this:

someGroovyObject.getProperty("property1.property2") 

It was difficult for me to find an example of others who wanted to do this, so perhaps I do not understand the basic concept of Groovy. There seems to be some elegant way to do this.

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

Any tips would be appreciated!

+8
properties nested groovy
source share
4 answers

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 verify 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') 
+22
source share

Groovy Beans allows you to directly access fields. You do not need to define getter / setter methods. They are created for you. Whenever you access the bean property, the getter / setter method is called internally. You can get around this behavior 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 call up 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 the field inside the collection, you need to select an element:

 assert 'BOA' == person.accounts[0].bankName assert 300 == person.accounts[1].balance​​​​​​​​​ 
+2
source share

You can also use propertyMissing . This is what you can call the Groovy 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:

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

This is automatically recursive and you do not need to explicitly call the method. This is only a getter, but you can define a second version with parameters to make a setter.

The downside is that, as far as I can tell, you can only define one version of propertyMissing , so you need to decide how to use dynamic navigation along the path for which you want to use it.

+1
source share

Cm

stack overflow

It uses the $ {} syntax, which can be used as part of a GString.

0
source share

All Articles