2012-12-15 14 views
6

Vorrei deserializzare JSON (con Jackson 1.9.11 e 1.0.1 RestTemplate), in cui un campo può avere più significati di tipo, per esempio:deserializzazione JSON con più tipi in un campo

{"responseId":123,"response":"error"} 

o

{"responseId":123,"response":{"foo":"bar", ... }} 

o uno o l'altro caso, funziona correttamente con un setter di tipo specifico (String od classe Response personalizzato), ma quando ho messo nel mio bean di entità setter sovresposta per essere in grado di gestire entrambi i casi, viene generata un'eccezione :

Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [xxxx.templates.ExportResponse] and content type [application/json;charset=utf-8] 

Stavo pensando a tre soluzioni, ma non ho avuto nessuno di loro lavoro:

  • utilizzando solo String setter e dentro uso ObjectMapper a unmarshall quella stringa, se non è uguale a "errore" , ma quando arriva JS Array, non è una stringa, quindi non viene usato String setter :(.
  • utilizza la gestione di tipo polimorfico (annotazione @JsonTypeInfo) con la propria estensione JsonDeserializer - Sto ancora cercando di capirlo e implementarlo.
  • crea l'elenco di HttpMessageConverter e inserisce tutti i convertitori di messaggi, che posso usare. Ma io questo passaggio non è necessario, perché viene utilizzato solo MappingJacksonHttpMessageConverter, vero?

EDIT: come funziona la società

Setter in bean entità:

@JsonDeserialize(using = ResponseDeserializer.class) 
public void setResponse(Object responseObject) { 
    if(responseObject instanceof Response) 
     response = (Response) responseObject; 
} 

metodo Deserialize in ResponseDeserializer:

public Response deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException { 
    Response response = new Response(); 

    if(JsonToken.START_OBJECT.equals(parser.getCurrentToken())) { 
     ObjectMapper mapper = new ObjectMapper(); 
     response = mapper.readValue(parser, Response.class); 
    } else 
     throw new JsonMappingException("Unexpected token received."); 

    return response; 
} 
+0

vi consiglio di utilizzare Jackson parser per lato server manipolazione di oggetti JSON –

+0

Sto lavorando sul lato client, il server non è il mio business :( – shmoula

risposta

7

L'unico modo per raggiungere questo obiettivo è quello di utilizzare un deserializzatore personalizzato.

Ecco un esempio:

ObjectMapper mapper = new ObjectMapper(); 
SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null)); 
testModule.addDeserializer(Response.class, new ResponseJsonDeserializer()); 
mapper.registerModule(testModule); 

E qui è come scrivere (come avrei scritto almeno) il deserializzatore:

class ResponseJsonDeserializer extends JsonDeserializer<Response> { 
    @Override 
    public Responsedeserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
    Response response = new Response(); 
    if(jp.getCurrentToken() == JsonToken.VALUE_STRING) { 
     response.setError(jp.getText()); 
    } else { 
     // Deserialize object 
    } 
    return response; 
    } 
} 

class Response { 
    private String error; 
    private Object otherObject; // Use the real type of your object 

    public boolean isError() { 
     return error != null; 
    } 

    // Getters and setters 

} 
+0

Sono d'accordo, sto provando a farlo in un modo simile, come ho scritto (con @JsonDeserialize (using = ResponseDataDeserializer.class)), quindi se lo faccio funzionare, segnerò la risposta :) – shmoula

+0

OK, funziona in questo modo, codice funzionante allegato alla domanda originale. Grazie. – shmoula

Problemi correlati