Deserializza stringa come elenco di stringhe
Ho un POJO che contiene i seguenti attributi
public class Example {
@JsonProperty("inputFoo")
private String foo
@JsonProperty("inputBar")
private String bar
@JsonProperty("inputBaz")
@JsonDeserialize(using = MyDeserializer.class)
private Set<String> baz
}
Il JSON con cui sto lavorando per rappresentare questi dati attualmente rappresenta l'attributo baz come una singola stringa:
{"inputFoo":"a", "inputBar":"b", "inputBaz":"c"}
Sto usando Jackson ObjectMapper per tentare di convertire il JSON nel mio POJO. So che la stringa baz di input da JSON non verrà mappata in modo pulito al set in cui sto cercando di rappresentarla, quindi ho definito un deserializzatore personalizzato:
public class MyDeserializer extends StdDeserializer<Set<String>> {
public MyDeserializer(){}
public MyDeserializer(Class<?> vc) {
super(vc);
}
public Set<String> deserialize(JsonParser p, DeserializationContext cxt) throws IOException, JsonProcessingException {
String input = p.readValueAs(String.class);
Set<String> output = new HashSet<>();
if(input != null) {
output.add(input);
}
return output;
}
}
Ricevo un'eccezione IllegalArgumentException che fa riferimento all'attributo "inputBaz", su cui posso fornire dettagli. Qualcuno vede qualche problema evidente con l'implementazione del mio deserializzatore? Grazie
Risposte
Non è necessario implementare un deserializzatore personalizzato, utilizza la funzione ACCEPT_SINGLE_VALUE_AS_ARRAY . Funziona anche per i set:
Funzionalità che determina se è accettabile forzare i valori non array (in JSON) a lavorare con i tipi di raccolta Java (array, java.util.Collection) . Se abilitato, i deserializzatori di raccolta proveranno a gestire i valori non di matrice come se avessero "implicito" intorno alla matrice JSON. Questa funzionalità è pensata per essere utilizzata per motivi di compatibilità / interoperabilità, per lavorare con pacchetti (come i convertitori da XML a JSON) che escludono l'array JSON nei casi in cui è presente solo un singolo elemento nell'array. La funzionalità è disabilitata per impostazione predefinita.
Guarda anche:
- com.fasterxml.jackson.databind.exc.MismatchedInputException: impossibile deserializzare l'istanza del java.util.ArrayListtoken START_OBJECT
Sostituisci i 2 costruttori con questo costruttore no-arg:
public MyDeserializer() {
super(TypeFactory.defaultInstance().constructCollectionType(Set.class, String.class));
}
ACCEPT_SINGLE_VALUE_AS_ARRAY come suggerito è una buona opzione.
Forse il tuo problema attuale è più complicato, ma in caso contrario potresti anche provare al @JsonCreatorposto del deserializzatore personalizzato. Piace:
public class Example {
@JsonCreator
public Example(@JsonProperty("inputFoo") String foo,
@JsonProperty("inputBar") String bar,
@JsonProperty("inputBaz") String strBaz) {
this.foo = foo;
this.bar = bar;
this.baz = new HashSet<>();
baz.add(strBaz);
}
private String foo;
private String bar;
private Set<String> baz;
}
Solo per mostrare che in un caso più generale potresti evitare di implementare il deserializzatore personalizzato @JsonCreatoranche con, ma comunque fare alcune semplici conversioni.