Groovy - Ignore extra attributes in a map during object instantiation

岁酱吖の 提交于 2020-03-18 03:18:38

问题


Is there a way to make groovy ignore extra attributes in a map during object instantiation? Example:

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

In this example, groovy throws a No such property: age exception (obviously because age isn't defined in the Banana class. Without resorting to manually mapping only the desired attributes from the map to the constructor of the Banana class, is there a way to tell Banana to ignore the extra attributes?

I noticed that Grails domain classes do not suffer from this problem, and I would like the same behavior here!

Thanks for your help and advice!


回答1:


Unfortunately, there's no built in way to do this in groovy. Grails does it by generating its own constructors for domain objects. A simple workaround is to use a constructor like this:

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



回答2:


There is a simpler way to deal with this case.

In your bean, just implement a trait

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



回答3:


Another way that does not impact performance if all properties are present:

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)
    }
}



回答4:


Similar to @JiankuanXing's answer (which is a perfect answer :) ), but instead of using trait your class can extends Expando and add the propertyMissing method:

class Banana extends Expando {
    String name

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

The use of trait fits probably better this case since it allow behavior composition and you can add the trait to all the class object which need it. I only add this alternative since Expando can be used since groovy 1.5 version while traits are introduced in groovy 2.3.

Hope it helps,



来源:https://stackoverflow.com/questions/10195653/groovy-ignore-extra-attributes-in-a-map-during-object-instantiation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!