Jackson反序列化:如何复用父对象值构建子对象属性?
嘿,这个问题我刚好处理过——用@JacksonInject确实能完美解决Child的version同步Parent的需求,下面我给你拆解具体的实现步骤,保证你一看就懂:
实现步骤
1. 改造实体类,标记需要注入的字段
先给Child类的version字段加上@JacksonInject,指定一个注入key(比如"parentVersion"),告诉Jackson这个字段的值不是从JSON里读取,而是要从外部注入:
public class Child { // 用@JacksonInject标记,指定注入的唯一标识key @JacksonInject("parentVersion") private int version; // 其他业务字段、构造函数、getter/setter省略 }
Parent类保持正常结构,后续会给它绑定自定义反序列化器:
@JsonDeserialize(using = ParentDeserializer.class) public class Parent { private int version; private Child child; // 无参构造、全参构造、getter/setter省略 }
2. 自定义Parent反序列化器,动态注入version值
核心思路是:在反序列化Parent的过程中,先读取JSON里的version值,再把这个值作为注入参数传递给Child的反序列化流程。
实现自定义反序列化器:
public class ParentDeserializer extends StdDeserializer<Parent> { // 无参构造,指定要反序列化的目标类型 public ParentDeserializer() { super(Parent.class); } @Override public Parent deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { // 1. 把JSON解析成JsonNode,方便单独读取各个字段 JsonNode parentNode = jsonParser.getCodec().readTree(jsonParser); // 2. 提取Parent的version值 int parentVersion = parentNode.get("version").asInt(); // 3. 创建注入上下文,将parentVersion绑定到之前指定的key InjectableValues injectableValues = new InjectableValues.Std() .addValue("parentVersion", parentVersion); // 4. 用带注入值的上下文反序列化Child Child child = jsonParser.getCodec().treeToValue( parentNode.get("child"), Child.class, injectableValues ); // 5. 组装Parent对象并返回 Parent parent = new Parent(); parent.setVersion(parentVersion); parent.setChild(child); return parent; } }
3. 测试验证
写个简单的测试代码,验证反序列化后Child的version是否和Parent完全一致:
public class TestDeserialization { public static void main(String[] args) throws IOException { ObjectMapper objectMapper = new ObjectMapper(); // 模拟业务中的JSON载荷 String jsonPayload = "{\"version\":2,\"child\":{}}"; Parent parent = objectMapper.readValue(jsonPayload, Parent.class); // 输出验证结果 System.out.println("Parent version: " + parent.getVersion()); // 输出2 System.out.println("Child version: " + parent.getChild().getVersion()); // 输出2 } }
替代方案(不用Inject的简化版)
如果你觉得自定义反序列化器有点繁琐,还有更轻量化的方式:在Parent的setChild方法里手动同步version值,完全不需要依赖Jackson的注入机制:
public void setChild(Child child) { this.child = child; // 主动同步Parent的version到Child if (child != null) { child.setVersion(this.version); } }
不过既然你明确想使用@JacksonInject,前面的方案完全匹配你的需求。
内容的提问来源于stack exchange,提问作者pintoch
相关产品推荐
相关产品推荐

