Groovy - 在对象实例化期间忽略地图中的额外属性

时间:2012-04-17 17:00:16

标签: groovy map constructor attributes ignore

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

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

在这个例子中,groovy抛出一个没有这样的属性:年龄异常(显然因为在Banana类中没有定义age。如果不依靠手动映射地图中所需的属性到Banana类的构造函数,是有办法告诉Banana忽略额外的属性吗?

我注意到Grails域类没有遇到这个问题,我想在这里做同样的行为!

感谢您的帮助和建议!

4 个答案:

答案 0 :(得分:16)

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

在你的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

答案 1 :(得分:11)

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

Banana(Map map) {
    metaClass.setProperties(this, map.findAll { key, value -> this.hasProperty(key) })
}

答案 2 :(得分: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)
    }
}

答案 3 :(得分:2)

类似于@JiankuanXing的答案(这是一个完美的答案:)),但您的课程可以扩展trait而不是使用Expando并添加propertyMissing方法:< / p>

class Banana extends Expando {
    String name

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

使用trait可能更适合这种情况,因为它允许行为组合,您可以将trait添加到需要它的所有类对象。我只添加了此替代方法,因为Expando版本可以使用groovy 1.5,而groovy 2.3中引入了traits

希望它有所帮助,