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

Java中无根JSON数组转POJO:API错误响应映射问题

解决方案

要解决成功响应(对象)和失败响应(无根数组)的统一映射问题,你需要通过自定义Jackson反序列化器处理两种JSON格式,并调整WebClient的错误状态码处理逻辑,具体步骤如下:

1. 补全Error实体类

确保Error类结构与第三方返回的错误字段完全匹配:

@Data
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class Error {
    private String errorCode;
    private String errorMessage;
}

2. 编写自定义Jackson反序列化器

创建反序列化器,判断输入JSON的类型(对象/数组),分别解析并组装成Response对象:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectCodec;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ResponseDeserializer extends JsonDeserializer<Response> {

    @Override
    public Response deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        ObjectCodec codec = parser.getCodec();
        JsonNode rootNode = codec.readTree(parser);
        
        Response.ResponseBuilder responseBuilder = Response.builder();
        
        if (rootNode.isArray()) {
            // 失败场景:将数组解析为Error列表
            List<Error> errorList = new ArrayList<>();
            for (JsonNode errorNode : rootNode) {
                Error error = codec.treeToValue(errorNode, Error.class);
                errorList.add(error);
            }
            responseBuilder.errors(errorList);
        } else if (rootNode.isObject()) {
            // 成功场景:直接解析为Response对象
            Response successResp = codec.treeToValue(rootNode, Response.class);
            responseBuilder.total(successResp.getTotal())
                    .errorCode(successResp.getErrorCode())
                    .errorMessage(successResp.getErrorMessage())
                    .description(successResp.getDescription())
                    .ordersList(successResp.getOrdersList());
        }
        
        return responseBuilder.build();
    }
}

3. 为Response类绑定反序列化器

在Response类上添加注解,指定使用自定义反序列化器:

@JsonIgnoreProperties(ignoreUnknown = true)
@Data
@Builder
@JsonDeserialize(using = ResponseDeserializer.class) // 绑定自定义反序列化器
public class Response {
    private int total;
    private String errorCode;
    private String errorMessage;
    private String description;
    private List<Order> ordersList;
    private List<Error> errors;
}

4. 调整WebClient的错误处理逻辑

第三方失败响应通常返回非200状态码,默认WebClient会抛出异常,需通过onStatus捕获错误状态码,将响应体解析为Response后返回,实现统一处理:

Response response = webClient
        .post()
        .uri(url, uri -> uri.queryParam(Constants.QUERY_PARAM).build())
        .header("Content-Type", "application/json")
        .bodyValue(request)
        .retrieve()
        // 捕获所有错误状态码,解析响应体为Response
        .onStatus(HttpStatus::isError, clientResponse -> 
            clientResponse.bodyToMono(Response.class)
                    .flatMap(Mono::just)
        )
        .bodyToMono(Response.class)
        .block();

验证逻辑

  • 当API返回200 OK的对象JSON时,反序列化器会填充ordersList等业务字段,errors字段为null
  • 当API返回失败的数组JSON时,反序列化器会将数组解析为errors列表,其他字段保持默认值(或null)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 13:02:03