2016-08-17 2 views
1

Je JSON structuré comme:tableau Deserialize JSON carte en utilisant Jackson

{ 
    "id" : "123", 
    "name" : [ { 
    "stuff" : [ { 
     "id" : "234", 
     "name" : "Bob" 
    }, { 
     "id" : "345", 
     "name" : "Sally" 
    } ] 
    } ] 
} 

que je veux carte à la structure de données suivantes:

MyInterface1

@Value.Immutable 
@JsonSerialize(as = ImmutableMyInterface1.class) 
@JsonDeserialize(as = ImmutableMyInterface1.class) 
public interface MyInterface1 { 
    String id(); 
    @JsonDeserialize(using = MyInterface1Deserializer.class) 
    List<MyInterface2> name(); 
} 

MyInterface2

@Value.Immutable 
@JsonSerialize(as = ImmutableMyInterface2.class) 
@JsonDeserialize(as = ImmutableMyInterface2.class) 
public interface MyInterface2 { 
    @JsonDeserialize(using = StuffDeserializer.class) 
    Map<String, MyInterface3> stuff(); 
} 

MyInterface3

@Value.Immutable 
@JsonSerialize(as = ImmutableMyInterface3.class) 
@JsonDeserialize(as = ImmutableMyInterface3.class) 
public interface MyInterface3 { 
     String id(); 
     String name(); 
} 

J'utilise un ObjectMapper avec readValue(stringWithJson,MyInterface1.class) pour cartographier ce JSON à MyInterface1, qui devrait se poursuivre dans la chaîne à MyInterface3. Cette configuration fonctionnait lorsque j'utilisais une liste dans MyInterface2, par exemple List<MyInterface3> name();

Cependant, je veux que ce soit une carte au lieu d'une liste, idéalement avec "id" du JSON interne comme clé. Cela me permettrait d'obtenir des valeurs avec la syntaxe suivante: MyInterface1.get(0).MyInterface2.get("id1").name();

Le problème est que lorsque vous essayez de créer une coutume StuffDeserializer.class, je reçois l'erreur: Can not deserialize instance of com.foo.ImmutableMyInterface2$Json out of START_ARRAY token

en essayant de le faire: Je pense que c'est parce que Jackson s'attend à ce que "stuff" soit une cause de List du tableau JSON. Quelle est la meilleure façon de désérialiser ce JSON sur une carte qui utilise les valeurs du JSON interne comme clé?

Répondre

0

Je voudrais créer une coutume JsonDeserializer à la carte id et name dans une carte:

public class StringHashMapValueDeserializer extends JsonDeserializer<HashMap<String, String>>{ 

    @Override 
    public HashMap<String, String> deserialize(JsonParser parser, DeserializationContext ctxt) 
      throws IOException, JsonProcessingException { 
     HashMap<String, String> ret = new HashMap<String, String>(); 

     ObjectCodec codec = parser.getCodec(); 
     TreeNode node = codec.readTree(parser); 

     if (node.isArray()){ 
      for (JsonNode n : (ArrayNode)node){ 
       JsonNode id = n.get("id"); 
       if (id != null){ 
        JsonNode name = n.get("name"); 
        ret.put(id.asText(), name.asText()); 
       } 
      } 
     } 
     return ret; 
    } 
} 

Et puis je voudrais créer des haricots simples avec annoter stuff propriété avec désérialiseur:

@Getter 
@Setter 
public class Name { 

    @JsonDeserialize(using = StringHashMapValueDeserializer.class) 
    Map<String, String> stuff; 

    @Override 
    public String toString() { 
     return "Name [stuff=" + stuff + "]"; 
    } 
} 

Type extérieur :

@Getter 
@Setter 
public class OuterType { 

    String id; 
    List<Name> name; 

    @Override 
    public String toString() { 
     return "OuterType [id=" + id + ", stuff=" + name + "]"; 
    } 
} 

Désérialisation:

ObjectMapper mapper = new ObjectMapper(); 

OuterType response; 
response = mapper.readValue(json, OuterType.class); 

System.out.println(response); 
System.out.println(response.getName().get(0).getStuff().get("234")); 

sortie de la console:

OuterType [id=123, stuff=[Name [stuff={234=Bob, 345=Sally}]]] 
Bob 

Hope it helps.