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)
Infatti, ho appena scoperto questo biglietto: http://jira.codehaus.org/browse/JACKSON-711 – killy971
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