2012-04-17 11 views
15

C'è un modo per far sì che Groovy ignori gli attributi extra in una mappa durante l'istanza dell'oggetto? Esempio:Groovy - Ignora attributi extra in una mappa durante l'istanza dell'oggetto

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

In questo esempio, scanalato lancia un No tale proprietà: eccezione età (ovviamente perché l'età non è definito nella classe Banana Senza ricorrere alla mappatura manualmente solo gli attributi desiderati dalla mappa al costruttore. della classe banana, c'è un modo per dire Banana di ignorare gli attributi aggiuntivi?

ho notato che Grails classi di dominio non soffrono di questo problema, e mi piacerebbe lo stesso comportamento qui!

Grazie per il tuo aiuto e il tuo consiglio!

risposta

10

Sfortunatamente, non c'è un modo per farlo in groovy. Grails lo fa generando i propri costruttori per gli oggetti di dominio. Una soluzione semplice è quella di utilizzare un costruttore come questo:

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

Ovviamente, è necessario assicurarsi che la vostra mappa params non contiene le chiavi 'class' o' metaClass', o eccezioni/stranezze ne seguirà ;-) –

+0

Thank you - mi piace questo caratteristica dei graal, speravo che non fosse attraverso astuti trucchi, ma che fosse invece una caratteristica del linguaggio. Oh bene. La tua soluzione alternativa dovrebbe fare il trucco, grazie! – Quad64Bit

2

Un altro modo che non influisce sulle prestazioni se tutte le proprietà sono presenti:

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

C'è un modo più semplice per affrontare questo caso.

Nel vostro fagioli, basta implementare un tratto

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

Modo davvero elegante per risolvere questo problema. –

+0

Ho usato con successo questo approccio nella console Groovy (v2.4.8) ma quando provo a fare lo stesso nel mio progetto Groovy ottengo un java.lang.VerifyError che si lamenta della firma del metodo di propertyMissing ?! Qualcuno ha un'idea del perché? – Emil

1

Simile a @ di JiankuanXing risposta (che è una risposta perfetta :)), ma invece di utilizzare trait tua lattina classe estende Expando e aggiungere il metodo propertyMissing :

class Banana extends Expando { 
    String name 

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

L'uso di trait si adatta probabilmente meglio questo caso dal momento che permettono un comportamento compo sizione ed è possibile aggiungere trait a tutti gli oggetti di classe che ne hanno bisogno. Aggiungo solo questa alternativa poiché Expando può essere utilizzata dalla versione groovy 1.5 mentre traits vengono introdotte in groovy 2.3.

Speranza che aiuta,

Problemi correlati