2016-08-17 12 views
1

を使用してマップします逆シリアル化JSON配列は、私は、JSONのような構造をしているジャクソン

MyInterface1

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

MyInterface2を:私は次のようなデータ構造にマップする

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

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

私はMyInterface3にチェーンを下り続けるべきMyInterface1にこのJSONをマッピングするためにreadValue(stringWithJson,MyInterface1.class)とObjectMapperを使用しています。この設定は、MyInterface2でListを使用していたときに機能していました。つまりList<MyInterface3> name();

ですが、これはリストの代わりにマップにするのが理想的です。内側のJSONのIDをキーとして使用するのが理想的です。これは、私は、次の構文を使用して値を取得できるようになります。やろうとしたときに Can not deserialize instance of com.foo.ImmutableMyInterface2$Json out of START_ARRAY token

MyInterface1.get(0).MyInterface2.get("id1").name();

問題は、カスタムStuffDeserializer.classを作成しようとしたとき、私はエラーを取得していますということです。

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

私はマップにidnameをマップするカスタムJsonDeserializerを作成します。

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 

はそれがお役に立てば幸いです。

関連する問題