我创建了一个类,允许生成的对象添加任意属性。该类还具有一些预定义的属性。在类的方法中,我希望能够遍历对象实例拥有的所有属性。
以下是一个示例类定义:
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.
}
}
有没有办法做我想做的事?
修改
我的目标之一是不必在toJsonString
方法中明确命名我的预定义属性。我希望能够在以后添加新的预定义属性,而不必记住更新toJsonString
方法。
编辑(2011年10月24日):
接受的答案给了我所需的信息。但是,它仍然需要我命名我不希望包含在JSON字符串中的属性。稍微扩展答案可以解决这个问题:
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] ]
}
为此,您必须明确指定类属性的修饰符。我的示例中的String bar = "baz"
应为public String bar = "baz"
,以便将其包含在JSON字符串中。
答案 0 :(得分:7)
有这种可能性(假设我有棒的右端); - )
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)
}
}
如果你没有Groovy 1.7.9+,那么行
def outObject = Foo.declaredFields.findAll { !it.synthetic && it.name != 'props' }.collectEntries { v ->
[ (v.name):this[v.name] ]
}
应替换为:
def outObject = Foo.declaredFields.findAll { !it.synthetic && it.name != 'props' }.inject([:]) { m, v ->
m << [ (v.name):this[v.name] ]
}
我相信它会表现得一样;即:如果我这样做:
def f = new Foo()
f.tim = 'yates'
println f.toJsonString()
打印出来:
{"bar":"baz","myNumber":42,"tim":"yates"}
答案 1 :(得分:0)
如果您想坚持使用此实现,可能会覆盖getProperties
以包含您的属性地图将是最简单的。