You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jackson如何兼容JSON对象/字符串格式反序列化成员对象

实现方案

Jackson完全支持该需求,无需修改全局ObjectMapper配置,仅通过字段注解+自定义反序列化器即可同时兼容两种JSON格式,实现步骤如下:

1. 编写自定义反序列化器

核心逻辑是在反序列化details字段时,先判断当前JSON节点的类型:如果是嵌套JSON对象,走默认解析逻辑;如果是字符串类型,先取出字符串内容,再将字符串内容作为JSON二次解析为UserDetails对象。

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;

public class FlexibleUserDetailsDeserializer extends JsonDeserializer<UserDetails> {
    // 内部复用ObjectMapper解析字符串内嵌的JSON,可按需单独配置序列化规则
    private static final ObjectMapper INNER_MAPPER = new ObjectMapper();

    @Override
    public UserDetails deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        // 匹配details为字符串的场景
        if (parser.currentToken() == JsonToken.VALUE_STRING) {
            String detailsJsonStr = parser.getValueAsString();
            return INNER_MAPPER.readValue(detailsJsonStr, UserDetails.class);
        }
        // 匹配details为正常JSON对象的场景,走默认解析逻辑
        return parser.readValueAs(UserDetails.class);
    }
}

2. 给目标字段添加注解指定反序列化器

在User类的details字段上添加@JsonDeserialize注解,绑定上面实现的自定义反序列化器即可。注意需要保证Jackson能访问到实体类的字段/属性,要么写全getter/setter,要么配置Jackson允许直接访问私有字段。

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

public class User {
    Integer id;
    @JsonDeserialize(using = FlexibleUserDetailsDeserializer.class)
    UserDetails details;

    //  getter/setter 示例,也可通过Lombok的@Data注解自动生成
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public UserDetails getDetails() { return details; }
    public void setDetails(UserDetails details) { this.details = details; }
}

对应的UserDetails类同理补全getter/setter即可:

public class UserDetails {
    String name;
    Integer age;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}

效果验证

直接运行测试代码即可正常解析两种格式的JSON,不会抛出类型不匹配异常,两种场景下User对象的id、details.name、details.age属性都能正确赋值:

ObjectMapper mapper = new ObjectMapper();
// 解析嵌套对象格式的JSON
User user1 = mapper.readValue(jsonString1, User.class);
// 解析details为JSON字符串格式的JSON
User user2 = mapper.readValue(jsonString2, User.class);

补充说明:该方案为字段级配置,仅对User类的details字段生效,不会影响ObjectMapper对其他业务对象的反序列化逻辑,侵入性极低。

内容的提问来源于stack exchange,提问作者samarendra chandan bindu Dash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 02:33:09