2016-08-17 91 views
1

我已經JSON結構類似:反序列化JSON陣列地圖使用傑克遜

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

,我想映射到數據結構如下:

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(); 
} 

我使用的是readValue(stringWithJson,MyInterface1.class)的ObjectMapper映射這個JSON來MyInterface1,應繼續環比下滑至MyInterface3。當我在MyInterface2中使用列表時,此設置正在工作,即List<MyInterface3> name();

但是,我希望這是一個映射而不是列表,理想情況下內部JSON中的「id」作爲鍵。這將允許我使用下面的語法獲取值: MyInterface1.get(0).MyInterface2.get("id1").name();

的問題是,試圖創建一個自定義StuffDeserializer.class的時候,我發現了錯誤:試圖做的時候 Can not deserialize instance of com.foo.ImmutableMyInterface2$Json out of START_ARRAY token

public Map<String, MyInterface3> deserialize(JsonParser jsonParser, DeserializationContext ctxt) 
     throws IOException { 

    MyInterface2 foo = Unmarshaller.OBJECT_MAPPER.readValue(jsonParser, MyInterface2.class); // error here 
    ... 

我想這是因爲傑克遜期待「stuff」成爲JSON數組的List的原因。將此JSON反序列化爲使用內部JSON值作爲關鍵字的映射的最佳方法是什麼?

回答

0

我想創建一個自定義JsonDeserializer映射idname成圖:

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; 
    } 
} 

然後,我將創建簡單的豆註釋stuff屬性與解串器:

@Getter 
@Setter 
public class Name { 

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

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

外類型:

@Getter 
@Setter 
public class OuterType { 

    String id; 
    List<Name> name; 

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

反序列化:

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")); 

控制檯輸出:

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

希望它能幫助。