2015-01-22 13 views
7

mi deserializzare jsons come questo:deserializzazione con @JsonSubTypes per nessun valore - mancante errore proprietà

{ 
    "type":"a", 
    "payload" : {...} 
} 

dove tipo di carico utile dipende dal tipo. La mia classe:

public class Sth<T extends Payload> { 

    @JsonProperty("type") 
    private String type; 
    @Valid 
    private T payload; 

    @JsonTypeInfo(
     use = JsonTypeInfo.Id.NAME, 
     include = JsonTypeInfo.As.EXTERNAL_PROPERTY, 
     property = "type", 
     visible = true, 
     defaultImpl = NoClass.class) 
    @JsonSubTypes({ 
     @JsonSubTypes.Type(value = APayload.class, name = "a"), 
     @JsonSubTypes.Type(value = BPayload.class, name = "b"), 
     @JsonSubTypes.Type(value = CPayload.class, name = "c")}) 
    public void setPayload(T payload) { 
    this.payload = payload; 
    } 

    public void setType(String type) { 
    this.type = type; 
    } 

} 

Ho anche digitato "d" senza carico utile. Se provo a deserializzare:

{ 
    "type":"d", 
    "payload" : null 
} 

funziona ma non funziona senza carico utile:

{ 
    "type":"d", 
} 

Come farlo funzionare con ultimo esempio?

Stacktrace di errore che ottengo:

[error] Caused by: com.fasterxml.jackson.databind.JsonMappingException: Missing property 'payload' for external type id 'type 
[error] at [Source: N/A; line: -1, column: -1] 
[error]  at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164) 
[error]  at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:700) 
[error]  at com.fasterxml.jackson.databind.deser.impl.ExternalTypeHandler.complete(ExternalTypeHandler.java:160) 
[error]  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithExternalTypeId(BeanDeserializer.java:690) 
[error]  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithExternalTypeId(BeanDeserializer.java:639) 
[error]  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:266) 
[error]  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:124) 
[error]  at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:2965) 
[error]  at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1587) 
[error]  at com.fasterxml.jackson.databind.ObjectMapper.treeToValue(ObjectMapper.java:1931) 
[error]  at play.libs.Json.fromJson(Json.java:47) 

risposta

1

Ho anche incontrato questo problema, e non poteva trovare una soluzione elegante utilizzando i meccanismi previsti da Jackson (personalizzato BeanDeserializer, BeanDeserializerModifier, etc.).

Sembra un bug nel modo in cui vengono gestiti gli ID dei tipi esterni. Ho lavorato intorno a:

  1. deserializzazione del JSON tring su un JsonNode;
  2. inserimento manuale di un nodo null se la proprietà richiesta non è presente;
  3. associazione del JsonNode al tipo di valore desiderato.

Il mio codice simile a quanto segue:

public <T> T decode(String json, Class<T> type) throws IOException { 
    JsonNode jsonNode = mapper.readTree(json); 

    if (jsonNode.isObject() && (jsonNode.get("payload") == null || jsonNode.get("payload").size() == 0)) { 
     ObjectNode objectNode = (ObjectNode) jsonNode; 
     objectNode.putNull("payload"); 
    } 

    return mapper.treeToValue(jsonNode, type); 
} 
+1

che in realtà è quello che ho fatto. Ho fatto la stessa domanda sul forum di Jackson e AFAIK non c'è soluzione migliore di questa. Ti sei perso un caso. Jackson non può deserializzare correttamente l'oggetto quando il carico utile non è impostato O è impostato come {}, quindi ho modificato la risposta e l'ho accettata. – jasiustasiu

+0

@jasiustasiu La tua modifica è stata rifiutata? Cosa vuoi cambiare? –

+0

Non so perché la mia modifica è stata rifiutata. Ho modificato la tua risposta di nuovo e sembra funzionare ora – jasiustasiu

1

credo di aver incontrato lo stesso problema che si documentato.

che stavo ricevendo la seguente eccezione

com.fasterxml.jackson.databind.JsonMappingException: Missing property 'content' 
    for external type id 'contentType 

ho finito per farlo funzionare con l'aggiunta del @JsonTypeId annotazioni al campo tipo.

public interface Content { 
} 

public class Post implements Content { 
    public String content = "bar"; 
} 

public class Foo { 

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 
       include = JsonTypeInfo.As.EXTERNAL_PROPERTY, 
       property = "contentType") 
    @JsonSubTypes({ 
    @JsonSubTypes.Type(value = Post.class, name = "post") 
    }) 
    public Content content; 

    @JsonTypeId 
    public ContentType contentType; 

    public enum ContentType { 
    "post" 
    } 
} 
1

C'è caratteristica esplicita deserializzazione per questo:

new ObjectMapper().configure(
DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY, 
false); 
+0

La modifica della configurazione è una buona soluzione, ma è meglio aggiungere alle proprietà dell'applicazione: 'spring.jackson.deserialization.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY' – reynev

Problemi correlati