Groovy – Simplest way of resolving a nested property
So let’s say that in Groovy you find yourself wanting to do something like this:
[ 'name', 'lastName', 'address.street'].collect { propertyToResolve -> [(propertyToResolve): user[property] }
You will find that the automatic getter (using it with the map syntax or as a property doesn’t change anything) won’t parse the argument to resolve the property in the whole object graph, but it will just search for a property in the object where is called (which absolutely make sense, of course 😀 ).
The next piece of code is one that I like to have in my typical grailsUtils bean:
def resolveNestedProperty(bean, String nestedProperty) { nestedProperty.tokenize('.').inject(bean) { valueSoFar, property -> valueSoFar[property] } }
Then you will be able to resolve the previous example by doing:
[ 'name', 'lastName', 'address.street'].collect { propertyToResolve -> [(propertyToResolve): grailsUtils.resolveNestedProperty(property, user) }
Yes, yes, I know: nothing really fancy or new, but it came in handy many times and I wanted to write it down 😀 .
Update: I updated the method in order to be more powerful (using Eval) yet faster when possible (by detecting if the expression needs Eval or not using regular expressions). So now it looks like the following:
static resolveNestedProperty(bean, String nestedProperty) { nestedProperty ==~ /[a-zA-Z0-9]+/ ? bean[nestedProperty] : nestedProperty ==~ /[a-zA-Z0-9.]+/ ? nestedProperty.tokenize('.').inject(bean) { valueSoFar, property -> valueSoFar ? valueSoFar[property] : null } : Eval.me('bean', bean, "bean.${nestedProperty}") }
Parecidos razonables
-
Grails – Hibernate-safe domain class property editor
July 22, 2014
0 -
Grails – Quickly examine a domain class associations
July 30, 2013
0 -
Grails – generic methods for equals and hashCode calculation
December 27, 2012
3 -
Grails – query or criteria against a string/value pairs map property
April 21, 2014
0 -
Groovy – using parameters with default values to separate method configuration from method body
November 23, 2012
0
Pingback: Grails – Quickly examine a domain class associations
How about:
[“name”, “lastName”, “address.street”].inject([:]) { m, property ->
m[property] = Eval.me(“user”, user, “user.$property”); m
}
?
That’s funky :-)! I think you could even simplify it more by using collectEntries instead of inject… like:
[“name”, “lastName”, “address.street”].collectEntries { property ->
[ (property): Eval.me(“user”, user, “user.$property”) ]
}
I knew about the Eval stuff but I’ve never used it. I’ll have to look into it, for this kind of debugging utilities seems pretty useful! Thanks for the input :-D.
I discovered that using Eval is extremely slow (which shouldn’t be surprising). I updated the post with my new proposed solution :).