2015-02-07 9 views
7

supponga serializzazione JSON include il nome classe dell'oggetto reale, utilizzando questa annotazione sulla Classe:Jackson può determinare il tipo di oggetto radice da deserializzare a quando json include la proprietà type?

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@type") 
class MyClass { 
    String foo; 
} 

Così JSON è per esempio:

{"@type": "com.example.MyClass", "foo": "bar"} 

questo può essere deserializzato senza specificare il tipo ? E intendo nemmeno il super-tipo. Proprio qualcosa del tipo:

objectMapper.readValue(value, Object.class); 

che in realtà non funziona, riporta una mappa.

risposta

5

Beh, è ​​certamente possibile farlo anche se personalmente non ho mai usato Jackson in quel modo. È possibile deserializzare un oggetto JsonNode e quindi convertirlo nel tipo corretto.

final ObjectMapper objectMapper = new ObjectMapper(); 
final MyClass myClass = new MyClass(); 
myClass.foo = "bar"; 

// Serialize 
final String json = objectMapper.writeValueAsString(myClass); 

// Deserialize 
final JsonNode jsonNode = objectMapper.readTree(json); 

// Get the @type 
final String type = jsonNode.get("@type").asText(); 

// Create a Class-object 
final Class<?> cls = Class.forName(type); 

// And convert it 
final Object o = objectMapper.convertValue(jsonNode, cls); 

System.out.println(o.getClass()); 

L'output è:

MiaClasse

+2

Oh, sì, immagino che funzioni. Mi stavo chiedendo se esistesse un modo più integrato, ma immagino che non avrebbe alcun senso visto che Jackson non poteva sapere come ho configurato JsonTypeInfo, senza conoscere la classe. Molte grazie. –

1

Sì, ma c'è un avvertimento: la digitazione si danno deve essere qualcosa che include @JsonTypeInfo specificato. Object.class non avrà, a meno che non si usi "annotazioni mix-in" per associarlo.

Tuttavia, se è necessario aggiungere informazioni sul tipo per le proprietà di (tipo dichiarato di) java.lang.Object, è consigliabile abilitare la digitazione predefinita: vedere ObjectMapper.enableDefaultTyping(...) per ulteriori informazioni. Ciò consentirà effettivamente l'inclusione (e l'uso) delle informazioni sul tipo per categorie di classi più grandi, senza necessità di aggiungere annotazioni.

2
ObjectMapper mapper = new ObjectMapper(); 
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 

    MyClass original = new MyClass(); 
    original.foo = "hello"; 

    String json = mapper.writeValueAsString(original); 
    MyClass foo = (MyClass) mapper.readValue(json, MyClass.class); 

Questo dovrebbe funzionare ed è molto conveniente.

+0

Funziona se si sa che JSON rappresenta 'MyClass' al momento della deserializzazione. Ho preso la domanda per fare riferimento a uno scenario in cui non si conosce il tipo di oggetto. Questa è la situazione che sto attualmente cercando di gestire. –

+0

Se non conosci il tipo, puoi semplicemente assegnarlo a un oggetto. Object.getClass() ti dirà di che tipo si tratta. – sydraz

Problemi correlati