迭代对象';Groovy中有哪些自己的属性?

迭代对象';Groovy中有哪些自己的属性?,groovy,Groovy,我创建了一个类,它允许结果对象添加任意属性。该类还具有一些预定义的属性。在类的方法中,我希望能够迭代对象实例拥有的所有属性 下面是一个示例类定义: import groovy.json.* class Foo { private Map props = [:] String bar = "baz" def myNumber = 42 void propertyMissing(String name, Object value) { this.

我创建了一个类,它允许结果对象添加任意属性。该类还具有一些预定义的属性。在类的方法中,我希望能够迭代对象实例拥有的所有属性

下面是一个示例类定义:

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字符串中。

如果您想坚持使用此实现,可能覆盖以包含您的属性映射是最简单的。

有这种可能性(假设我得到了棍子的右端);-)

应替换为:

        def outObject = Foo.declaredFields.findAll { !it.synthetic && it.name != 'props' }.inject([:]) { m, v ->
          m << [ (v.name):this[v.name] ]
        }
它打印出:

{"bar":"baz","myNumber":42,"tim":"yates"}

如果我正确理解了您的建议,那么标准的
fooInstance.properties()
方法已经包含(实际上不是)私有映射。我用我的目标的更多信息更新了我的问题。@jsumnes它包括映射,但作为映射,而不是作为“顶级”属性的条目。我的意思是创建一个
getProperties
,它不将映射作为映射包含,而是将映射的键作为属性名公开,将值作为这些属性的值公开。好的。这是有道理的。但是,当我
def getProperties(){返回this.props.keySet()}
时,尝试设置动态属性会导致“无此类属性”错误。此外,我仍然希望排除继承的属性,如“类”和“元类”,而不必提前了解它们。这个答案并没有解决问题的这一部分。你不能只返回这个.props.keySet(),因为那样你就会错过实际的属性;这就是为什么我说要包含属性映射的条目。元类属性的列表很短且已知,或者可以通过筛选super.properties显式删除super/meta类属性。但是你考虑过只使用ExpandoMetaClass吗?这就是为什么我以“坚持这个实现”开头,因为Groovy已经有了一种默认方式来表示一个直到运行时才知道其属性的类;这是漫长的一天。但是,我仍然有这个问题,因为现在我似乎无法创建groovy.lang.MetaProperty的实例。解释器要么在我的“Foo”对象上查找元属性方法,要么在“groovy”对象上找不到“lang”(即
groovy.lang.MetaProperty
)。让我澄清一下:我不知道Groovy。一个实际的例子将使我受益匪浅。谢谢。这正是我想要做的。
        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"}