2011-12-01 10 views
6

Con Jackson biblioteca json, è possibile deserializzare oggetto attraverso l'uso del @JsonCreator, e dare la mappa "top level" che rappresenta il json ingresso, come segue:Uso @JacksonInject con @JsonCreator su una mappa di livello superiore

class MyClass { 
    final int field; 

    @JsonCreator 
    public MyClass(Map<String, Object> map) { 
     this.field = (int) map.get("theInt"); 
    } 
} 

persino su un metodo factory statico:

class MyClass { 
    final int field; 

    public MyClass(int theInt) { 
     this.field = theInt; 
    } 

    @JsonCreator 
    static MyClass create(Map<String, Object> map) { 
     return new MyClass((int) map.get("theInt")); 
    } 
} 

Gli esempi precedenti possono elaborare i seguenti tipi di ingresso json:

{ 
    "key1":"value1", 
    "key2":"value2", 
    "key3":"value3" 
} 

Questo è particolarmente utile nel mio caso, perché mi piacerebbe deserializzare un json quale struttura non conosco. Avere accesso a quella che io chiamo la "mappa di livello superiore" rende le cose semplici.

Vorrei deserializzare miei oggetti in questo modo in quanto consente anche di creare oggetti immutabili, invece di usare @JsonAnySetter che non consente questo, e @JsonProperty che non posso usare come io non conosco il nome proprietà in anticipo come ho detto prima.

Poi andare oltre, vorrei iniettare qualche configurazione nel mio metodo di fabbrica, e Jackson permette questo attraverso l'uso di @JacksonInject e una chiamata al withInjectableValues(InjectableValues) sul ObjectMapper.

questo è alla fine il tipo di codice vorrei utilizzare:

class MyClass { 
    final MyField[] myFields; 

    public MyClass(MyField... myFields) { 
     this.myFields = myFields; 
    } 

    @JsonCreator 
    static MyClass create(@JacksonInject("conf") Conf conf, Map<String, Object> map) { 
     MyFields[] myFields; 
     // initialize myFields (or any other object) based on the content of map 
     // and also make use of the inject conf 
     return new MyClass(myFields); 
    } 
} 

Purtroppo, Jackson tiri il seguente tipo di eccezioni:

  • quando si cerca il trucco sul costruttore

JsonMappingException: Argument #1 of constructor [constructor for MyClass, annotations: {[email protected]()}] has no property name annotation; must have name when multiple-paramater constructor annotated as Creator

  • quando si cerca il trucco sul metodo factory

JsonMappingException: Argument #1 of factory method [method create, annotations: {[email protected]()}] has no property name annotation; must have when multiple-paramater static method annotated as Creator

Qualcuno sa come potrei risolvere il problema?

Per riassumere i requisiti, ho bisogno:

  • accesso alla mappa di livello superiore (non so i nomi delle proprietà JSON in anticipo)
  • Per creare un oggetto immutabile (quindi non può utilizzare @JsonAnySetter)
  • per iniettare un po 'conf al metodo @JsonCreator decorato costruttore o in fabbrica

non posso cambiare il formato di input jSON, che assomiglia a questo:

{ 
    "key1":"value1", 
    "key2":"value2", 
    "key3":"value3" 
} 

[EDIT]

Questo è un problema noto: http://jira.codehaus.org/browse/JACKSON-711 (non ancora fissata)

risposta

4

Destra, che si desidera sia utilizzato per "delegare" creatore (singolo argomento, nella quale ingresso JSON è prima associato) - diverso dal creatore "basato sulla proprietà" in cui vengono passati i parametri nominati e i valori iniettabili. Questo dovrebbe funzionare idealmente, ma penso che potrebbe non funzionare al momento. Penso che ci sia una Jira inserita per questo, quindi puoi controllarlo (http://jira.codehaus.org/browse/JACKSON).

Solo per essere sicuri: stai usando la versione 1.9.2? Ci sono state alcune correzioni in questo sono dalla 1.9.0; quale almeno darebbe un messaggio di errore migliore.

+0

Infatti, ho appena scoperto questo biglietto: http://jira.codehaus.org/browse/JACKSON-711 – killy971

+0

Ah sì. Assicurati di votare per questo - come ho detto, dovrebbe funzionare, ma è una delle combinazioni più complicate da supportare, purtroppo, solo per gli aspetti dell'implementazione. – StaxMan