23

有没有办法让 groovy 在对象实例化期间忽略地图中的额外属性?例子:

class Banana{
    String name
}
def params = [name:'someGuy', age:13]
new Banana(params)

在这个例子中,groovy 抛出一个 No such property: age 异常(显然是因为年龄没有在 Banana 类中定义。不求助于手动将地图中的所需属性映射到 Banana 类的构造函数,有没有办法告诉香蕉忽略额外的属性?

我注意到 Grails 域类不会遇到这个问题,我希望这里有同样的行为!

感谢您的帮助和建议!

4

4 回答 4

21

有一种更简单的方法来处理这种情况。

在你的bean中,只需实现一个特征

trait IgnoreUnknownProperties {
    def propertyMissing(String name, value){
        // do nothing
    }
}

class Person implements IgnoreUnknownProperties {
    String name
}

map = ["name": "haha", "extra": "test"]
Person p = new Person(map)

println p.name
于 2015-06-09T08:18:06.717 回答
13

不幸的是,在 groovy 中没有内置的方法可以做到这一点。Grails 通过为领域对象生成自己的构造函数来实现这一点。一个简单的解决方法是使用这样的构造函数:

Banana(Map map) {
    metaClass.setProperties(this, map.findAll { key, value -> this.hasProperty(key) })
}
于 2012-04-17T17:18:44.313 回答
2

如果所有属性都存在,另一种不会影响性能的方法:

public static Banana valueOf(Map<String, Object> params) {
    try {
        return new Banana(source)
    } catch (MissingPropertyException e) {
        log.info(e.getMessage())
        source.remove(e.property)
        return valueOf(source)
    }
}
于 2013-09-17T09:51:34.480 回答
2

类似于@JiankuanXing 的答案(这是一个完美的答案:)),但不是使用trait你的类可以扩展Expando和添加propertyMissing方法:

class Banana extends Expando {
    String name

    def propertyMissing(name, value) {
        // nothing
    }
}
def params = [name:'someGuy', age:13]
new Banana(params)

在这种情况下使用traitfit 可能会更好,因为它允许行为组合,并且您可以将它添加trait到所有需要它的类对象中。我只添加了这个替代方案,因为Expando可以使用groovy 1.5版本 whiletraitsgroovy 2.3.

希望能帮助到你,

于 2016-02-26T10:34:22.170 回答