当前位置: 首页 > 知识库问答 >
问题:

在Jackson中反序列化同名但不同类型的属性?

范福
2023-03-14

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

{
    "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 中帮助我将 JSON 中的通道映射到字符串类型(当它是字符串)和通道类型(当它是 JSON 对象时)

或者换句话说,Jackson中是否有一种方法可以通过变量的type映射,而不仅仅是通过name

共有1个答案

通安宁
2023-03-14

我可以建议你这样使用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
 类似资料:
  • 问题内容: 我有一个REST API,它返回JSON响应为: 有时它返回: 我有一个像这样的POJO: 那么,有没有一种方法(不是写你自己的其他 自定义解串器 中)Jackson2,这将有助于我映射在JSON来时,它的A型和类型时,它是一个JSON对象? 或者换句话说,在Jackson中,有没有一种方法可以按变量而不是by 映射? 问题答案: 我可以建议您像这样使用JsonNode: 或像这样 :

  • 我想实现一个功能,其中请求映射到正确的对象。是否有一种方法(除了自定义反序列化器)可以将请求按类型/基数映射到适当的对象?任何见解都将不胜感激!

  • 序列化和反序列化的方式不同于 我已经创建了两个序列化程序 和 我用Jackson查看了序列化/反序列化映射 ,但找不到解决方案。

  • 我的Spring Boot API使用camelCase,但我需要通过我的API将一些请求代理到使用snake_case的第三方API。是否可以将Jackson配置为从snake_case反序列化第三方响应,然后将其序列化回camelCase到我的前端? 所需功能的逐步示例: 示例对象: 我调用我的API API调用第三方 第三方返回 我的API将其反序列化为 我的API序列化对象并返回 现在我使

  • 问题内容: 是否可能:在类中有一个字段,而在Jackson库中进行序列化/反序列化时却为其使用不同的名称? 例如,我有“ Coordiantes”类。 对于从JSON反序列化,希望具有以下格式: 但是当我序列化对象时,结果应该是这样的: 我试图通过在getter和setter上都应用注释(具有不同的值)来实现此目的: 但我有一个例外: org.codehaus.jackson.map.exc.Un

  • 问题内容: 我如何才能序列化一个特定的属性,但又防止其反序列化回POCO?是否可以使用属性装饰特定属性? 基本上,我正在寻找一个与ShouldSerialize *方法等效的反序列化方法。 我知道我可以编写一个自定义转换器,但是这样做似乎有点过头了。 编辑: 这里还有一些背景。这背后的原因是我的课看起来像: 我需要请求的属性,但是我不希望它反序列化并触发设置程序逻辑。 问题答案: 最简单的方法是将