在Jackson中反序列化具有相同名称但不同类型的属性

在Jackson中反序列化具有相同名称但不同类型的属性

本文介绍了在Jackson中反序列化具有相同名称但不同类型的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个REST API,它返回的JSON响应为:

  {
channel: JHBHS
}

有时返回:

  {
channel:{
id:12321,
name:某些频道
}
}

我有一个POJO,如:

  public class Event {
private String channel;
@JsonProperty( channel)
私人频道channelObj;
}

公共类频道{
private int id;
私有字符串名称;
}

那么,有没有办法(除了编写自己的自定义反序列化器)在中,这将帮助我映射频道 String 类型的 String Channel 是JSON对象时的类型?



换句话说,在Jackson中,有没有一种方法可以通过类型进行映射变量而不仅仅是 name

解决方案

我建议您使用像这样:

  class事件{

@JsonProperty( channel)
私人JsonNode channelInternal;

私人频道;

私有字符串channelStr;

/ **
*带有通道解析的自定义获取器
* @return channel
* /
public Channel getChannel(){
if (channel == null&& channelInternal!= null){
if(channelInternal.isObject()){
int id = channelInternal.get( id)。intValue();
字符串名称= channelInternal.get(名称).asText();
channel = new Channel(id,name);
}
}
返回频道;
}

/ **
*自定义带有通道字符串解析的吸气剂
* @返回通道字符串
* /
public String getChannelStr( ){
if(channelStr == null&& channelInternal!= null){
if(channelInternal.isTextual()){
channelStr = channelInternal.asText();
}
}
返回channelStr;
}
}

或类似的

 类事件{

私人频道;

私有字符串channelStr;

@JsonSetter( channel)
public void setChannelInternal(JsonNode channelInternal){
if(channelInternal!= null){
if(channelInternal.isTextual() ){
channelStr = channelInternal.asText();
}否则if(channelInternal.isObject()){
int id = channelInternal.get( id)。intValue();
字符串名称= channelInternal.get(名称).asText();
channel = new Channel(id,name);
}
}
}

public Channel getChannel(){
返回频道;
}

public String getChannelStr(){
return channelStr;
}
}

但我认为使用自定义反序列化器更为常见。 / p>

这里是测试代码

  public static void main(String [] args)引发IOException {
ObjectMapper objectMapper = new ObjectMapper();
字符串source1 = {\n +
\ channel\:\ JHBHS\ \n +
};
字符串source2 = {\n +
\ channel\:{\n +
\ id\:12321,\ n +
\ name\:\某些频道\ \n +
} \n +
};

//测试对象解析
事件结果= objectMapper.readValue(source2,Event.class);
System.out.println(String.format(%s:%s,result.getChannel()。getId(),result.getChannel()。getName()));

//测试字符串解析
结果= objectMapper.readValue(source1,Event.class);
System.out.println(result.getChannelStr());
}

输出:

  12321:某些频道
JHBHS


I have a REST API which returns a JSON response as:

{
    "channel" : "JHBHS"
}

and sometimes it returns:

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

I have a POJO like:

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

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

So, is there a way (other than writing your own custom deserializer) in Jackson2 which will help me map channel in JSON to String type when it's a String and Channel type when it's a JSON Object?

Or in other words, is there a way in Jackson which maps by type of the variable and not just by name?

解决方案

I can suggest you to use JsonNode like this:

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

or like this:

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

But I think using custom deserializer is more common.

Here is test code

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

And the output:

12321 : Some channel
JHBHS

这篇关于在Jackson中反序列化具有相同名称但不同类型的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 11:38