Java对比两个JSON文件反序列化属性全为null问题排查
问题根因
你遇到的反序列化属性全为null的问题,核心是2个映射配置错误:
@JsonRootName注解未生效:Jackson默认不会识别根元素包裹注解,需要额外开启配置才能生效,且你的JSON结构并不符合该注解的使用场景。- 类型匹配错误:JSON根节点下的
pickEventActivities是数组类型,数组内的元素才对应你定义的PickEvent结构,直接把整个JSON反序列化为单个PickEvent类,类型完全不匹配,自然所有属性都是null。
另外PickEvent类中的lineNbr属性定义为String,但JSON中对应值是数值类型,存在类型转换隐患。
修复步骤
步骤1:修正POJO映射逻辑
两种方案选其一即可:
方案A:新增外层包装类(推荐,结构最清晰)
去掉PickEvent类上的@JsonRootName注解,新增一层和JSON根结构匹配的包装类:
@Data public class PickEventWrapper { private List<PickEvent> pickEventActivities; }
修正PickEvent的lineNbr属性类型:
@Data @JsonPropertyOrder({ "orderId", "lineNbr", "pick"}) class PickEvent { String orderId; Integer lineNbr; // 修正为数值类型和JSON匹配 String pick; List<Activation> activations; }
方案B:不新增类,手动解析JSON节点
如果你不想新增包装类,可以先把JSON读为JsonNode,再提取pickEventActivities节点转换为列表:
// 反序列化示例 JsonNode root1 = objectMapper.readTree(new File("src/../pickevent1.json")); JsonNode activitiesNode1 = root1.get("pickEventActivities"); List<PickEvent> list1 = objectMapper.convertValue(activitiesNode1, new TypeReference<List<PickEvent>>() {}); PickEvent result1 = list1.get(0);
步骤2:调整反序列化逻辑
以方案A为例,调整测试代码的反序列化部分:
public void compareJson() throws Exception { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(ACCEPT_SINGLE_VALUE_AS_ARRAY, true); // 改为反序列化为包装类 PickEventWrapper wrapper1 = objectMapper.readValue(new File("src/../pickevent1.json"), PickEventWrapper.class); PickEventWrapper wrapper2 = objectMapper.readValue(new File("src/../pickevent2.json"), PickEventWrapper.class); PickEvent result1 = wrapper1.getPickEventActivities().get(0); PickEvent result2 = wrapper2.getPickEventActivities().get(0); // 不要用assertSame,assertSame是对比对象引用,不同实例哪怕属性相同也会报错 // 要对比内容可以用assertEquals,或者用下面的方案输出具体差异 }
步骤3:实现差异定位(可选但推荐)
如果需要直接输出具体的差异字段,不要只用JUnit的assertEquals,改用AssertJ的递归对比功能,会自动打印所有不一致的属性位置:
首先引入AssertJ依赖(Maven示例):
<dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.24.2</version> <scope>test</scope> </dependency>
然后替换断言逻辑:
assertThat(result1) .usingRecursiveComparison() .isEqualTo(result2);
运行后会直接输出类似以下的差异结果,可直接定位问题:
- field "orderId" : expected "115", but was "215" - field "lineNbr" : expected 1, but was 0 - field "pick" : expected "Hello", but was "EACH" - field "activations[0].activationType" : expected "Bi", but was "Si" - field "activations[0].activationValue" : expected "3", but was "31"
内容的提问来源于stack exchange,提问作者Rumi
相关产品推荐
相关产品推荐

