在对象实例化期间,有没有办法让groovy忽略地图中的额外属性?例如:
class Banana{
String name
}
def params = [name:'someGuy', age:13]
new Banana(params)
在这个例子中,groovy抛出一个没有这样的属性:年龄异常(显然因为在Banana类中没有定义age。如果不依靠手动映射地图中所需的属性到Banana类的构造函数,是有办法告诉Banana忽略额外的属性吗?
我注意到Grails域类没有遇到这个问题,我想在这里做同样的行为!
感谢您的帮助和建议!
答案 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
。
希望它有所帮助,