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

Java对比两个JSON文件反序列化属性全为null问题排查

问题根因

你遇到的反序列化属性全为null的问题,核心是2个映射配置错误:

  1. @JsonRootName注解未生效:Jackson默认不会识别根元素包裹注解,需要额外开启配置才能生效,且你的JSON结构并不符合该注解的使用场景。
  2. 类型匹配错误: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 11:45:04