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对象的场景,实现方式如下:
- 定义Machine实体:
public class Machine { private String line; private String code; public Machine(String line, String code) { this.line = line; this.code = code; } // 按需添加getter、setter }
- 外层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。
示例代码:
- 给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; } }
- 自定义反序列化器实现:
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
相关产品推荐
相关产品推荐

