Jackson递归结构序列化问题:仅输出qNodeId,子节点丢失
Jackson递归结构序列化/反序列化问题修复
我定义了Node、CNode、QNode三种核心节点类型:QNode继承自最基础的Node类,包含额外字段,且可拥有CNode列表(CNode可引用其他CNode,但不会引用父QNode);QNode中可选包含TypeInfo类实例,而TypeInfo可拥有可选的Node引用。在使用Jackson将该递归结构序列化/反序列化为JSON与Java对象时,仅能获取QNode的qNodeId及其额外属性,子节点对象无法正常输出。
示例JSON输入
{ "qNodes": [ { "qNodeId": "Q-11122", "id": "PO11111", "typeInfo": { "applicationLevel": "medium", "required": true }, "cNodes": [ { "cNodeId": "Q-11155", "cNodes": [ { "qNodeId": "Q-7420", "typeInfo": { "applicationLevel": "low", "assetNode": { "id": "WQ-222", "qNode": { "qNodeId": "Q-0988" } }, "required": true }, "url": "https://example.com ", "id": "qS111" } ] } ] } ] }
问题分析
导致子节点无法正常反序列化的核心原因如下:
- 构造函数的
@JsonCreator参数与JSON字段不匹配,Jackson无法正确初始化对象 - 部分关键字段缺少
@JsonProperty注解,无法建立JSON与Java字段的映射 - 部分类缺少Lombok的
@Data注解,没有生成getter/setter,Jackson无法访问字段 - CNode类缺少子CNode列表字段,与JSON结构不匹配
修复后的代码实现
BaseNode类
修正@JsonAnySetter方法名,确保Jackson正确识别额外属性:
import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.NoArgsConstructor; import java.util.HashMap; import java.util.Map; @Data @NoArgsConstructor public class BaseNode { protected String id; protected Map<String, String> additionalProperties = new HashMap<>(); @JsonCreator public BaseNode(@JsonProperty("id") String id) { this.id = id; } @JsonAnySetter public void setAdditionalProperties(String property, String value) { this.additionalProperties.put(property, value); } }
Node类
简化构造函数,添加@JsonProperty确保字段映射:
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @Data public class Node { @JsonProperty("id") private String id; @JsonProperty("qNode") private QNode qNode; @JsonCreator public Node(@JsonProperty("id") String id, @JsonProperty("qNode") QNode qNode) { this.id = id; this.qNode = qNode; } }
TypeInfo类
添加@Data和@JsonProperty注解,修正枚举与JSON字符串的映射:
import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @Data public class TypeInfo { public enum Level { low, medium, high; } @JsonProperty("applicationLevel") private Level applicationLevel; @JsonProperty("assetNode") private Node assetNode; @JsonProperty("required") private boolean required; }
CNode类
添加子CNode列表字段,修正构造函数,添加必要注解:
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; @Data @JsonInclude(JsonInclude.Include.NON_NULL) public class CNode { @JsonProperty("cNodeId") private String cNodeId; @JsonProperty("qNode") private QNode qNode; @JsonProperty("cNodes") private List<CNode> cNodes; @JsonCreator public CNode(@JsonProperty("cNodeId") String cNodeId, @JsonProperty("qNode") QNode qNode, @JsonProperty("cNodes") List<CNode> cNodes) { this.cNodeId = cNodeId; this.qNode = qNode; this.cNodes = cNodes; } }
QNode类
修正构造函数参数,为typeInfo添加@JsonProperty,修正@JsonAnySetter方法:
import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.HashMap; import java.util.List; import java.util.Map; @Data public class QNode extends BaseNode { @JsonProperty("qNodeId") private String qNodeId; @JsonProperty("cNodes") private List<CNode> cNodes; @JsonProperty("typeInfo") private TypeInfo typeInfo; private Map<String, String> additionalElements = new HashMap<>(); @JsonCreator public QNode(@JsonProperty("id") String id, @JsonProperty("qNodeId") String qNodeId, @JsonProperty("cNodes") List<CNode> cNodes, @JsonProperty("typeInfo") TypeInfo typeInfo) { super(id); this.qNodeId = qNodeId; this.cNodes = cNodes; this.typeInfo = typeInfo; } @JsonAnySetter public void setAdditionalElements(String property, String value) { this.additionalElements.put(property, value); } }
QNodeContainer类
保持原结构即可:
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; @Data public class QNodeContainer { @JsonProperty("qNodes") private List<QNode> qNodes; @JsonCreator public QNodeContainer(@JsonProperty("qNodes") List<QNode> qNodes) { this.qNodes = qNodes; } }
反序列化代码
确保ObjectMapper配置正确,验证反序列化结果:
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.core.io.ClassPathResource; import java.io.File; import java.nio.file.Files; public class DeserializeDemo { public static void main(String[] args) throws Exception { File resource2 = new ClassPathResource("data.json").getFile(); String dataJson = new String(Files.readAllBytes(resource2.toPath())); ObjectMapper mapper = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); QNodeContainer qNodes = mapper.readValue(dataJson, QNodeContainer.class); // 验证反序列化结果 System.out.println(qNodes.getQNodes().get(0).getTypeInfo().getApplicationLevel()); System.out.println(qNodes.getQNodes().get(0).getCNodes().get(0).getCNodes().get(0).getQNodeId()); } }
内容的提问来源于stack exchange,提问作者BreenDeen
相关产品推荐
相关产品推荐

