2012-04-20 15 views
6

Sto utilizzando Spring's MappingJacksonHttpMessageConverter per convertire il messaggio JSON in oggetto nel mio controller.Deserialize ArrayList da String utilizzando Jackson

<bean id="jsonConverter" 
    class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
    <property name="prefixJson" value="false" /> 
    <property name="supportedMediaTypes" value="application/json" /> 
</bean> 

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="messageConverters"> 
     <list> 
      <ref bean="jsonConverter" /> 
     </list> 
    </property> 
</bean> 

Per i campi che vengono dichiarati come ArrayList, se il messaggio JSON contiene una stringa, invece, saranno gettati la seguente eccezione:

org.springframework.http.converter.HttpMessageNotReadableException: 
Could not read JSON: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token 

Un esempio potrebbe essere la definizione della classe di seguito:

public class Product { 
    private String name; 
    private List<String> images; 
} 

Qualora il JSON in arrivo è:

{name:"Widget", images:"image1.jpg"} 

AS si può vedere, questo produrrà l'eccezione poiché l'immagine dovrebbe essere una matrice.

Vorrei fare un deserializzatore personalizzato che è un po 'più tollerante. Se la deserializzazione fallisce, creare un ArrayList di un singolo elemento dalla stringa. Come faccio ad iniettare questo in MappingJacksonHttpMessageConverter o ObjectMapper?

Non sto cercando di utilizzare l'annotazione per contrassegnare ogni singolo campo ArrayList in modo da poter utilizzare una deserializzazione personalizzata. Sto cercando un modo per sovrascrivere il deserializzatore predefinito per preformare questa funzione.

+0

Qual è la stringa originale si sta cercando di deserializzare? –

+0

affermare che è {prodotto: "1234"} anziché {product: ["1234"]} – ltfishie

+0

e in che modo stai tentando di deserializzarlo? puoi pubblicare del codice? –

risposta

14

Dai un'occhiata a questo articolo che descrive come utilizzare le funzionalità di objectMapper di jackson per ottenere ciò.

https://github.com/FasterXML/jackson-dataformat-xml/issues/21

Per me aggiungendo il seguente risolto questo problema

jsonMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 
+4

o nella versione 2 jsonMapper.configure (DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); –

+3

Cristo, perché è stato così difficile trovarlo online? * Questa * è la soluzione che stavo cercando - grazie. – Ryan

1

Per quanto vedo il JSON in arrivo non contiene alcun array. La domanda è: le "immagini" dovrebbero essere separate o contenere una singola immagine? Supponiamo che siano separati da virgola:

public class Product { 
    private String name; 
    private List<String> images; 

    @JsonProperty("images") 
    public String getImagesAsString() { 
     StringBuilder sb = new StringBuilder(); 
     for (String img : images) { 
      if (sb.length() > 0) sb.append(','); 
      sb.append(img); 
     } 
     return sb.toString(); 
    } 

    public void setImagesAsString(String img) { 
     this.images = Arrays.asList(img.split(",")); 
    } 

    @JsonIgnore 
    public List<String> getImages() { 
     return images; 
    } 
} 
+0

Grazie per la tua risposta. Scusa se non l'ho chiarito, ma quello che sto cercando di fare è rendere l'analisi un po 'più tollerante. Voglio anche applicare questo al comportamento di parsing predefinito, quindi non ho bisogno di usare annotazioni o creare un metodo secondo setter per ogni campo. – ltfishie

+0

L'altra opzione consiste nel rendere il campo 'images' come una stringa semplice (se contiene una singola immagine), o modificare il formato della stringa JSON per inviare una matrice invece di una stringa. –

Problemi correlati