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

Java中多类型字段的JSON反序列化及POJO设计咨询

处理Java中多类型字段的JSON反序列化问题

首先明确你要处理的三种JSON结构:

变体1(仅字符串类型errorMessage):

{"errorMessage": "系统异常"}

变体2(含errorType和字符串errorMessage):

{"errorType": "VALIDATION", "errorMessage": "参数格式错误"}

变体3(含errorType和对象类型errorMessage):

{"errorType": "BUSINESS", "errorMessage": {"code": "BIZ-001", "message": "库存不足"}}

下面提供两种可行的解决方案,优先推荐第一种自定义反序列化器的方式,类型判断更清晰,代码可读性更强。


方案1:自定义反序列化器(推荐)

步骤1:定义基础数据类

首先定义对应变体3中errorMessage对象的实体类:

public class ErrorMessageDetail {
    private String code;
    private String message;

    // 必须有无参构造方法,Jackson反序列化需要
    public ErrorMessageDetail() {}

    // Getter & Setter
    public String getCode() { return code; }
    public void setCode(String code) { this.code = code; }
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
}

然后定义一个包装类,用来统一封装字符串和对象两种类型的errorMessage:

public class ErrorMessageWrapper {
    private String simpleMessage;
    private ErrorMessageDetail detailMessage;

    // 针对字符串类型的构造方法
    public ErrorMessageWrapper(String simpleMessage) {
        this.simpleMessage = simpleMessage;
    }

    // 针对对象类型的构造方法
    public ErrorMessageWrapper(ErrorMessageDetail detailMessage) {
        this.detailMessage = detailMessage;
    }

    // 判断当前是哪种类型的消息
    public boolean isSimpleMessage() {
        return simpleMessage != null;
    }

    // Getter方法
    public String getSimpleMessage() { return simpleMessage; }
    public ErrorMessageDetail getDetailMessage() { return detailMessage; }
}

步骤2:编写自定义反序列化器

创建一个反序列化器,根据JSON节点的类型,将errorMessage转换成对应的包装类实例:

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.ObjectMapper;

import java.io.IOException;

public class ErrorMessageDeserializer extends JsonDeserializer<ErrorMessageWrapper> {
    @Override
    public ErrorMessageWrapper deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        ObjectMapper mapper = (ObjectMapper) parser.getCodec();
        JsonNode node = mapper.readTree(parser);

        if (node.isTextual()) {
            // 字符串类型,直接返回包装了字符串的实例
            return new ErrorMessageWrapper(node.asText());
        } else if (node.isObject()) {
            // 对象类型,转换成ErrorMessageDetail后再包装
            ErrorMessageDetail detail = mapper.treeToValue(node, ErrorMessageDetail.class);
            return new ErrorMessageWrapper(detail);
        }
        return null;
    }
}

步骤3:定义主响应类并关联反序列化器

在主响应类中,给errorMessage字段标记使用自定义反序列化器:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

public class ErrorResponse {
    private String errorType;
    @JsonDeserialize(using = ErrorMessageDeserializer.class)
    private ErrorMessageWrapper errorMessage;

    // Getter & Setter
    public String getErrorType() { return errorType; }
    public void setErrorType(String errorType) { this.errorType = errorType; }
    public ErrorMessageWrapper getErrorMessage() { return errorMessage; }
    public void setErrorMessage(ErrorMessageWrapper errorMessage) { this.errorMessage = errorMessage; }
}

步骤4:测试反序列化

使用Jackson的ObjectMapper进行反序列化测试:

import com.fasterxml.jackson.databind.ObjectMapper;

public class DeserializeTest {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        // 测试变体1
        String json1 = "{\"errorMessage\": \"系统异常\"}";
        ErrorResponse res1 = mapper.readValue(json1, ErrorResponse.class);
        System.out.println("变体1消息:" + res1.getErrorMessage().getSimpleMessage());

        // 测试变体2
        String json2 = "{\"errorType\": \"VALIDATION\", \"errorMessage\": \"参数格式错误\"}";
        ErrorResponse res2 = mapper.readValue(json2, ErrorResponse.class);
        System.out.println("变体2类型:" + res2.getErrorType() + ",消息:" + res2.getErrorMessage().getSimpleMessage());

        // 测试变体3
        String json3 = "{\"errorType\": \"BUSINESS\", \"errorMessage\": {\"code\": \"BIZ-001\", \"message\": \"库存不足\"}}";
        ErrorResponse res3 = mapper.readValue(json3, ErrorResponse.class);
        if (!res3.getErrorMessage().isSimpleMessage()) {
            ErrorMessageDetail detail = res3.getErrorMessage().getDetailMessage();
            System.out.println("变体3类型:" + res3.getErrorType() + ",错误码:" + detail.getCode() + ",消息:" + detail.getMessage());
        }
    }
}

方案2:直接使用Object字段(快速实现)

如果不想写自定义反序列化器,可以直接将errorMessage定义为Object类型,在代码中通过类型判断来处理不同情况:

定义主响应类

public class ErrorResponse {
    private String errorType;
    private Object errorMessage;

    // Getter & Setter
    public String getErrorType() { return errorType; }
    public void setErrorType(String errorType) { this.errorType = errorType; }
    public Object getErrorMessage() { return errorMessage; }
    public void setErrorMessage(Object errorMessage) { this.errorMessage = errorMessage; }
}

测试反序列化

import com.fasterxml.jackson.databind.ObjectMapper;

public class QuickDeserializeTest {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        String json3 = "{\"errorType\": \"BUSINESS\", \"errorMessage\": {\"code\": \"BIZ-001\", \"message\": \"库存不足\"}}";
        ErrorResponse res3 = mapper.readValue(json3, ErrorResponse.class);

        if (res3.getErrorMessage() instanceof String) {
            System.out.println("字符串消息:" + (String) res3.getErrorMessage());
        } else if (res3.getErrorMessage() instanceof ErrorMessageDetail) {
            ErrorMessageDetail detail = (ErrorMessageDetail) res3.getErrorMessage();
            System.out.println("错误码:" + detail.getCode() + ",消息:" + detail.getMessage());
        }
    }
}

这种方式的缺点是类型判断分散在业务代码中,长期维护性不如方案1,但实现速度快,适合简单场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 20:23:12