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

如何用Jackson将第三方API可变JSON响应绑定到Java对象?

问题:Jackson适配第三方API的可变JSON响应

场景说明

第三方API返回两种JSON响应格式:

错误与成功数据混合的响应

{
    "errorCount": 2,
    "errorIndices": [
        0,
        1
    ],
    "data": [
        {
            "errorCode": 901,
            "errorMessage": "IBad data: Check the data",
            "errorData": "xxxx"
        },
        {
            "errorCode": 901,
            "errorMessage": "IBad data: Check the data",
            "errorData": "XZY"
        },
        "fun now"
    ]
}

全成功场景下的响应

{"errorCount": 0,"errorIndices": [],"data": ["fun now","try later"]}

现有代码问题

当前定义的ApiResponse类仅能适配全成功场景,无法处理混合场景:

public class ApiResponse { 
    @JsonProperty 
    private int errorCount;  
    @JsonProperty 
    private int[] errorIndices;  
    @JsonProperty 
    private String[] data;
    // 省略其他代码......
}

适配两种场景的实现方向

方案1:使用Object[]接收data字段

将data字段类型改为Object[],借助Jackson自动类型推断能力,直接将数组元素分别解析为String或错误对象,再通过errorIndices区分数据类型:

public class ApiResponse { 
    @JsonProperty 
    private int errorCount;  
    @JsonProperty 
    private int[] errorIndices;  
    @JsonProperty 
    private Object[] data;
    
    // 辅助方法:提取成功数据
    public List<String> getSuccessData() {
        List<String> successList = new ArrayList<>();
        Set<Integer> errorIndexSet = new HashSet<>(Arrays.stream(errorIndices).boxed().toList());
        for (int i = 0; i < data.length; i++) {
            if (!errorIndexSet.contains(i)) {
                successList.add((String) data[i]);
            }
        }
        return successList;
    }
    
    // 辅助方法:提取错误数据
    public List<ErrorInfo> getErrorData() {
        List<ErrorInfo> errorList = new ArrayList<>();
        Set<Integer> errorIndexSet = new HashSet<>(Arrays.stream(errorIndices).boxed().toList());
        for (int i = 0; i < data.length; i++) {
            if (errorIndexSet.contains(i)) {
                errorList.add((ErrorInfo) data[i]);
            }
        }
        return errorList;
    }
}

// 错误信息实体类
public class ErrorInfo {
    @JsonProperty
    private int errorCode;
    @JsonProperty
    private String errorMessage;
    @JsonProperty
    private String errorData;
    // 构造器、getter、setter省略
}

该方案实现简单,无需额外配置,适合大部分场景。

方案2:自定义反序列化器

编写自定义JsonDeserializer,在解析data数组时,根据节点类型动态判断是字符串还是错误对象:

public class DataDeserializer extends JsonDeserializer<List<Object>> {
    @Override
    public List<Object> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        List<Object> result = new ArrayList<>();
        JsonNode arrayNode = p.getCodec().readTree(p);
        if (arrayNode.isArray()) {
            for (JsonNode node : arrayNode) {
                if (node.isObject()) {
                    ErrorInfo errorInfo = p.getCodec().treeToValue(node, ErrorInfo.class);
                    result.add(errorInfo);
                } else if (node.isTextual()) {
                    result.add(node.asText());
                }
            }
        }
        return result;
    }
}

在ApiResponse的data字段上指定该反序列化器:

public class ApiResponse { 
    @JsonProperty 
    private int errorCount;  
    @JsonProperty 
    private int[] errorIndices;  
    @JsonProperty
    @JsonDeserialize(using = DataDeserializer.class)
    private List<Object> data;
    // 可根据业务需求添加数据提取方法
}

该方案灵活性更高,可自定义解析逻辑,适合复杂格式场景。

方案3:使用@JsonTypeInfo(不推荐)

若错误对象有固定标识字段(如errorCode),可尝试通过类型信息注解实现,但由于数组元素无统一父类标识,实现繁琐,不如前两种方案直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 02:01:17