2016-06-14 216 views
3

我有一個REST API返回的JSON響應爲:反序列化Jackson中同名但不同類型的屬性?

{ 
    "channel" : "JHBHS" 
} 

,有時它返回:

{ 
    "channel": { 
        "id": 12321, 
        "name": "Some channel" 
       } 
} 

我有這樣一個POJO:

public class Event { 
    private String channel; 
    @JsonProperty("channel") 
    private Channel channelObj; 
} 

public class Channel { 
    private int id; 
    private String name; 
} 

那麼,有沒有一種方式(除了寫你自己的定製解串器Jackson2這將幫助我映射channel在JSON到String類型時它是StringChannel類型時,它是一個JSON對象?

或換句話說,在傑克遜有沒有一種方法,通過變量type映射而不僅僅是name

+0

我發現了另一個類似的問題http://stackoverflow.com/questions/21790727/providing-jackson-mapper-multiple-方式反序列化同一對象 –

回答

5

我可以建議你使用JsonNode這樣的:

class Event { 

    @JsonProperty("channel") 
    private JsonNode channelInternal; 

    private Channel channel; 

    private String channelStr; 

    /** 
    * Custom getter with channel parsing 
    * @return channel 
    */ 
    public Channel getChannel() { 
     if (channel == null && channelInternal != null) { 
      if (channelInternal.isObject()) { 
       int id = channelInternal.get("id").intValue(); 
       String name = channelInternal.get("name").asText(); 
       channel = new Channel(id, name); 
      } 
     } 
     return channel; 
    } 

    /** 
    * Custom getter with channel string parsing 
    * @return channel string 
    */ 
    public String getChannelStr() { 
     if (channelStr == null && channelInternal != null) { 
      if (channelInternal.isTextual()) { 
       channelStr = channelInternal.asText(); 
      } 
     } 
     return channelStr; 
    } 
} 

或類似這樣的

class Event { 

    private Channel channel; 

    private String channelStr; 

    @JsonSetter("channel") 
    public void setChannelInternal(JsonNode channelInternal) { 
     if (channelInternal != null) { 
      if (channelInternal.isTextual()) { 
       channelStr = channelInternal.asText(); 
      } else if (channelInternal.isObject()) { 
       int id = channelInternal.get("id").intValue(); 
       String name = channelInternal.get("name").asText(); 
       channel = new Channel(id, name); 
      } 
     } 
    } 

    public Channel getChannel() { 
     return channel; 
    } 

    public String getChannelStr() { 
     return channelStr; 
    } 
} 

但我認爲使用自定義解串器爲多見。

下面是測試代碼

public static void main(String[] args) throws IOException { 
    ObjectMapper objectMapper = new ObjectMapper(); 
    String source1 = "{\n" + 
      " \"channel\" : \"JHBHS\"\n" + 
      "}"; 
    String source2 = "{\n" + 
      " \"channel\": {\n" + 
      "     \"id\": 12321,\n" + 
      "     \"name\": \"Some channel\"\n" + 
      "    }\n" + 
      "}"; 

    //Test object parsing 
    Event result = objectMapper.readValue(source2, Event.class); 
    System.out.println(String.format("%s : %s", result.getChannel().getId(), result.getChannel().getName())); 

    //Test string parsing 
    result = objectMapper.readValue(source1, Event.class); 
    System.out.println(result.getChannelStr()); 
} 

和輸出:

12321 : Some channel 
JHBHS 
+0

非常詳細的答案。但是不會像這個http://stackoverflow.com/a/27068928/1385441中那樣使用自定義setter方法來完成這項工作嗎? –

+0

@Ramswaroop,剛剛更新了第二個變體的答案,如http://stackoverflow.com/questions/21790727/providing-jackson-mapper-multiple-ways-to-deserialize-the-same-object/27068928#27068928 – Vadeg

相關問題