2012-04-17 15 views
15

¿Hay alguna manera de hacer que groovy ignore los atributos adicionales en un mapa durante la creación de instancias de objetos? Ejemplo:Groovy: Ignora atributos adicionales en un mapa durante la instanciación de objetos

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

En este ejemplo, maravilloso lanza un n tal propiedad: Excepción de edad (obviamente porque la edad no está definido en la clase Plátano Sin recurrir a mapear manualmente sólo los atributos deseados del mapa para el constructor. de la clase de plátano, ¿hay una manera de contar plátano hacer caso omiso de los atributos extra?

noté que Grails clases de dominio no sufren de este problema, y ​​me gustaría el mismo comportamiento aquí!

Gracias por su ayuda y consejo!

Respuesta

10

Desafortunadamente, no hay una forma integrada de hacerlo en Groovy. Grails lo hace al generar sus propios constructores para objetos de dominio. Una solución sencilla es utilizar un constructor de esta manera:

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

Obviamente, usted tiene que asegurarse de que su mapa params no contiene las claves '' class' o metaClass', o Excepciones/rareza se producirán ;-) –

+0

Gracias - Me gusta este característica de Grails, esperaba que no fuera a través de trucos ingeniosos, sino que era una función de idioma en su lugar. Oh bien. Sin embargo, su solución debería hacer el truco, ¡gracias! – Quad64Bit

2

Otra forma que no afecte el rendimiento si todas las propiedades están presentes:

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

Hay una manera más simple para hacer frente a este caso.

En el bean, simplemente aplicar un rasgo

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 
+0

Manera realmente elegante de resolver este problema. –

+0

He utilizado este enfoque con éxito en la consola Groovy (v2.4.8) pero cuando trato de hacer lo mismo en mi proyecto Groovy obtengo un java.lang.VerifyError quejándose de la firma del método de propertyMissing ?! ¿Alguien tiene una idea de por qué? – Emil

1

similares a la respuesta de @ JiankuanXing (que es una respuesta perfecta :)), pero en lugar de utilizar trait su lata clase extiende Expando y añadir el método propertyMissing :

class Banana extends Expando { 
    String name 

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

El uso de trait encaja probablemente mejor este caso, ya que permite un comportamiento compo y puede agregar el trait a todos los objetos de la clase que lo necesiten. Solo agrego esta alternativa ya que Expando se puede usar desde la versión groovy 1.5, mientras que traits se introducen en groovy 2.3.

creo que sirve,

Cuestiones relacionadas