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

Jackson如何基于另一属性值实现依赖属性的反序列化

实现方案

Jackson完全支持这种依赖其他属性的反序列化需求,推荐两种实现方式,按复杂度从低到高排列:

方案1:使用@JsonCreator构造方法(最推荐)

直接在实体类的构造方法上标注@JsonCreator,Jackson会将JSON中解析到的所有属性传入构造方法,你可以直接在构造逻辑中完成属性依赖的计算,不需要修改默认反序列化规则,也不用处理上下文问题。

简化示例代码:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;

public class Main {
    private static class Test {
        private String foo;
        private String bar;

        @JsonCreator
        public Test(@JsonProperty("foo") String foo, @JsonProperty("bar") String bar) {
            this.foo = foo;
            // 直接完成bar依赖foo的拼接逻辑
            this.bar = bar + "_" + foo;
        }

        @Override
        public String toString() {
            return "Test [foo=" + foo + ", bar=" + bar + "]";
        }
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        Test result = mapper.readValue("{\"foo\":\"a\",\"bar\":\"b\"}", Test.class);
        System.out.println(result); // 输出:Test [foo=a, bar=b_a]
    }
}

实际业务场景适配:

针对你提到的嵌套Machine对象的场景,实现方式如下:

  1. 定义Machine实体:
public class Machine {
    private String line;
    private String code;

    public Machine(String line, String code) {
        this.line = line;
        this.code = code;
    }
    // 按需添加getter、setter
}
  1. 外层DTO实现:
public class OuterDTO {
    private String line;
    private Machine machine;

    @JsonCreator
    public OuterDTO(@JsonProperty("line") String line, @JsonProperty("machine") String machineCode) {
        this.line = line;
        // 直接用外层line和传入的machine编码构造嵌套对象
        this.machine = new Machine(line, machineCode);
    }
    // 按需添加getter、setter
}

调用mapper.readValue("{\"line\":\"C12\", \"machine\": \"A\"}", OuterDTO.class)即可得到符合要求的实体。


方案2:字段级自定义反序列化器(适合逻辑复用场景)

如果多个字段/类都需要用到相同的依赖反序列化逻辑,可以自定义反序列化器,通过JsonParser#getCurrentValue()获取正在反序列化的父对象,拿到已解析的依赖属性值。

注意:该方案要求JSON中依赖的属性(如示例中的foo)必须出现在被依赖属性(如bar)的前面,否则拿到的依赖属性值为null。如果无法保证JSON字段顺序,优先使用方案1。

示例代码:

  1. 给Test类添加foo的getter方法:
private static class Test {
    @JsonProperty
    private String foo;
    @JsonProperty
    @JsonDeserialize(using = CustomDeserializer.class)
    private String bar;

    // 构造方法、toString省略
    public String getFoo() {
        return foo;
    }
}
  1. 自定义反序列化器实现:
private static class CustomDeserializer extends StdDeserializer<String> {
    protected CustomDeserializer() {
        super(String.class);
    }

    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        // 获取当前正在反序列化的父对象实例
        Test parent = (Test) p.getCurrentValue();
        String foo = parent.getFoo();
        String currentValue = p.getValueAsString();
        return foo == null || foo.isEmpty() ? currentValue : currentValue + "_" + foo;
    }
}

内容的提问来源于stack exchange,提问作者lelmarir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 16:06:05