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

如何使用Jackson将复杂JSON数组解析为对应Java类?

实现方案

原JSON的dataBlock数组包含多个headingName节点,我们需要将这些节点按其name字段映射到MyResponse的对应属性上,同时保证未来新增heading时的扩展性。可以通过自定义Jackson反序列化器结合通用基类来实现:

1. 定义通用属性类

所有headingName下的attributes结构统一,先创建通用的Attribute类处理多类型的value:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Attribute {
    private String name;
    private String position;
    // 兼容字符串、数组、对象等多种value类型,后续可按需转换
    private Object value;
}

2. 定义通用Heading基类

所有具体的Heading类继承该基类,统一包含name、position、attributes字段:

@Data
@NoArgsConstructor
@AllArgsConstructor
public abstract class BaseHeading {
    private String name;
    private String position;
    private List<Attribute> attributes;
}

3. 定义具体的Heading类

根据JSON中的name字段创建对应实体类,继承基类即可(后续有特殊字段可直接扩展):

// 对应"name": "Operational Information"
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class OperationalInformation extends BaseHeading {}

// 对应"name": "CRA"
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class CRA extends BaseHeading {}

4. 实现自定义反序列化器

核心逻辑是遍历dataBlock数组,根据headingName的name值映射到MyResponse的对应属性:

public class MyResponseDeserializer extends StdDeserializer<MyResponse> {

    public MyResponseDeserializer() {
        super(MyResponse.class);
    }

    @Override
    public MyResponse deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        MyResponse response = new MyResponse();
        JsonNode rootNode = p.getCodec().readTree(p);
        JsonNode dataBlockNode = rootNode.get("dataBlock");

        if (dataBlockNode != null && dataBlockNode.isArray()) {
            ObjectMapper mapper = (ObjectMapper) p.getCodec();
            for (JsonNode itemNode : dataBlockNode) {
                JsonNode headingNode = itemNode.get("headingName");
                String headingName = headingNode.get("name").asText();

                // 根据headingName匹配对应类,赋值到MyResponse属性
                switch (headingName) {
                    case "Operational Information":
                        OperationalInformation info = mapper.treeToValue(headingNode, OperationalInformation.class);
                        response.setOperationalInformation(info);
                        break;
                    case "CRA":
                        CRA cra = mapper.treeToValue(headingNode, CRA.class);
                        response.setCra(cra);
                        break;
                    // 未来新增heading时,添加对应case即可
                    default:
                        // 可忽略未知heading或做自定义处理
                        break;
                }
            }
        }
        return response;
    }
}

5. 配置MyResponse类

在MyResponse上指定自定义反序列化器,保留原有注解:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonDeserialize(using = MyResponseDeserializer.class) // 指定自定义反序列化器
public class MyResponse {
    private OperationalInformation operationalInformation;
    private CRA cra;
    // 未来新增heading时,添加对应属性即可
}

6. 测试反序列化

用Jackson验证解析效果:

public class TestDeserialization {
    public static void main(String[] args) throws IOException {
        String json = "你的目标JSON字符串";
        ObjectMapper mapper = new ObjectMapper();
        MyResponse response = mapper.readValue(json, MyResponse.class);
        
        // 验证解析结果
        System.out.println(response.getOperationalInformation().getName());
        System.out.println(((JsonNode)response.getCra().getAttributes().get(1).getValue()).get("line1").asText());
    }
}

扩展性说明

  • 未来新增headingName时,只需三步:
    1. 创建继承BaseHeading的实体类;
    2. 在MyResponse中添加该类的属性;
    3. 在反序列化器的switch中新增对应case分支。
  • 若某个heading需要特殊结构,直接修改对应实体类即可,不会影响其他模块。

内容的提问来源于stack exchange,提问作者saran3h

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 06:18:19