2014-01-11 9 views
9

Ich habe diese POJO:Jackson-Mapping-Objekt oder eine Liste von Objekt auf json Eingang je

public class JsonObj { 

    private String id; 
    private List<Location> location; 


    public String getId() { 
     return id; 
    } 

    public List<Location> getLocation() { 
     return location; 
    } 

    @JsonSetter("location") 
    public void setLocation(){ 
     List<Location> list = new ArrayList<Location>(); 
     if(location instanceof Location){ 
      list.add((Location) location); 
      location = list; 
     } 
    } 
} 

das „location“ Objekt aus dem json-Eingang kann entweder ein einfaches Beispiel von Standort oder ein Array von Ort sein. Wenn es nur eine Instanz ist, bekomme ich diesen Fehler:

Could not read JSON: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token 

Ich habe versucht, eine benutzerdefinierte Setter zu implementieren, aber es hat nicht funktioniert. Wie kann ich je nach json-Eingabe einen Standort oder eine Liste zuordnen?

+0

Verschiedene JSON bedeutet verschiedene JSON DTO. Wenn Ihr JSON ein '[]' hat, müssen Sie 'List' verwenden, wenn es ein' {} 'hat, benötigen Sie ein einfaches Objekt. –

+0

Es ist manchmal [] und manchmal {} für den gleichen Schlüssel und leider kann ich das nicht ändern. – TrtG

+1

Erstellen Sie einen benutzerdefinierten Deserializer, der prüft, ob es ein '[]' oder ein '{}' ist, und erstellt entsprechend eine Instanz und fügt sie der 'Liste' hinzu. –

Antwort

15

Update: Mher Sarkissian's soulution funktioniert gut, es kann auch mit Anmerkungen wie vorgeschlagen verwendet werden here, so:.

@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) 
private List<Item> item; 

Mein tiefstes Mitgefühl für dieses lästige Problem, ich hatte gerade das gleiche Problem und die Lösung hier gefunden: https://stackoverflow.com/a/22956168/1020871

Mit etwas Modifikation ich damit kommen, zuerst den generischen Klasse:

public abstract class OptionalArrayDeserializer<T> extends JsonDeserializer<List<T>> { 

    private final Class<T> clazz; 

    public OptionalArrayDeserializer(Class<T> clazz) { 
     this.clazz = clazz; 
    } 

    @Override 
    public List<T> deserialize(JsonParser jp, DeserializationContext ctxt) 
      throws IOException { 
     ObjectCodec oc = jp.getCodec(); 
     JsonNode node = oc.readTree(jp); 
     ArrayList<T> list = new ArrayList<>(); 
     if (node.isArray()) { 
      for (JsonNode elementNode : node) { 
       list.add(oc.treeToValue(elementNode, clazz)); 
      } 
     } else { 
      list.add(oc.treeToValue(node, clazz)); 
     } 
     return list; 
    } 
} 

und dann das Eigentum und die tatsächliche Deserializer-Klasse (Java Generics ist nicht immer schön):

@JsonDeserialize(using = ItemListDeserializer.class) 
private List<Item> item; 

public static class ItemListDeserializer extends OptionalArrayDeserializer<Item> { 
    protected ItemListDeserializer() { 
     super(Item.class); 
    } 
} 
+0

Danke für dieses Snippet, es hat mein Problem gelöst! Nur für den Fall [hier ist die Scala-Version des obigen Codes] (https://gist.github.com/Aivean/6bb90e3942f3bf966608). – Aivean

2

Dies wird bereits von jackson

objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 
unterstützt