Iterating an object's own properties in Groovy?
There's this possibility (assuming I've got the right end of the stick) ;-)
class Foo {
private Map props = [:]
String bar = "baz"
def myNumber = 42
void propertyMissing(String name, Object value) {
this.props[name] = value
}
def propertyMissing(String name) {
return this.props[name]
}
def toJsonString() {
def outObject = Foo.declaredFields.findAll { !it.synthetic && it.name != 'props' }.collectEntries { v ->
[ (v.name):this[v.name] ]
}
outObject << props
JsonOutput.toJson(outObject)
}
}
If you don't have Groovy 1.7.9+, then the lines
def outObject = Foo.declaredFields.findAll { !it.synthetic && it.name != 'props' }.collectEntries { v ->
[ (v.name):this[v.name] ]
}
Should be replaced with:
def outObject = Foo.declaredFields.findAll { !it.synthetic && it.name != 'props' }.inject([:]) { m, v ->
m << [ (v.name):this[v.name] ]
}
And I believe it will behave the same; ie: if I do this:
def f = new Foo()
f.tim = 'yates'
println f.toJsonString()
it prints out:
{"bar":"baz","myNumber":42,"tim":"yates"}
devdavid
I am the Linux administrator at Clayton State University in Morrow, GA. I deal primarily with RHEL server administration, but I do a fair amount of scripting and web development as well. But programming is more of a hobby for me than day job. My current interest is in Node.js.
Updated on June 08, 2022Comments
-
devdavid almost 2 years
I have created a class that allows the resulting object to have arbitrary properties added to it. The class also has some predefined properties. In a method of the class I want to be able to iterate over all properties owned by the instance of the object.
Here is an example class definition:
import groovy.json.* class Foo { private Map props = [:] String bar = "baz" def myNumber = 42 void propertyMissing(String name, Object value) { this.props[name] = value } def propertyMissing(String name) { return this.props[name] } def toJsonString() { def outObject = [:] // I want to do something like this this.properties.each { k, v -> if (this.isOwnProperty(k) && k != 'props') { outObject[k] = v } } outObject = outObject + this.props return JsonOutput.toJson(outObject) // Should return a string like: // {"bar":"baz", "myNumber":42, "someDynamicProperty":"value"} // // This string should not contain the "class" and "metaClass" // properties. } }
Is there a way to do what I am wanting to do?
Edit: One of my goals is to not have to explicitly name my predefined properties in the
toJsonString
method. I want to be able to add new predefined properties at a later date without having to remember to update thetoJsonString
method.Edit (24 October 2011):
The accepted answer gave me the information I needed. However, it still required me to name the properties I don't want included in the JSON string. Extending the answer a little bit solves this problem:
def outObject = Foo.declaredFields.findAll { // 'it' is a Field object returned by // http://download.oracle.com/javase/1,5,0/docs/api/java/lang/Class.html#getDeclaredFields() !it.synthetic && it.getModifiers() != java.lang.reflect.Modifier.PRIVATE }.collectEntries { v -> [ (v.name) : this[v.name] ] }
For this to work, you must explicitly specify the modifiers for your class properties. That is
String bar = "baz"
in my example should bepublic String bar = "baz"
in order for it to be included in the JSON string.