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

JSON转Java对象反序列化失败:空字符串字段处理求助

问题

定义如下Java类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class MatchingResponse {
    @JsonProperty(value = "Code")
    private String code;
    @JsonProperty(value = "Msg")
    private String message;
    @JsonProperty(value = "Id")
    private int id;
    @JsonProperty(value = "Date")
    private String date;
    @JsonProperty(value = "ClientIin")
    private String clientIin;
    @JsonProperty(value = "Similarity")
    private String similarity;
    @JsonProperty(value = "VendorName")
    private String vendorName;
}

尝试反序列化以下JSON:

{
    "Code": "200",
    "Msg": "",
    "Id": 20148,
    "Date": "2023-08-01T15:21:13.9704572+06:00",
    "ClientIin": "888888888888",
    "Similarity": "0.007720462",
    "VendorName": "SomeName"
}

使用Jackson的代码:

ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
byte[] byteResponse = httpResponse.getEntity().getContent().readAllBytes();
MatchingResponse response = mapper.readValue(byteResponse, MatchingResponse.class);

出现反序列化异常:

Cannot construct instance of `MatchingResponse` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"Code":"200","Msg":"","Id":20148,"Date":"2023-08-01T15:18:03.883337+06:00","ClientIin":"888888888888","Similarity":"0.0738383234","VendorName":"SomeName"}')
 at [Source: (byte[])"{\"Code\":\"200\",\"Msg\":\"\",\"Id\":20147,\"Date\":\"2023-08-01T15:18:03.883337+06:00\",\"ClientIin\":\"830921301593\",\"Similarity\":\"0.0738383234\",\"VendorName\":\"VisionLabs\"}""; line: 1, column: 1]

改用Gson也报错:

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 2 path $

尝试过添加@JsonSetter处理空字符串、自定义类级反序列化器、自定义String类型空字符串反序列化器等方法,均未解决问题。需要解决该反序列化错误,正确处理JSON中的空字符串字段。

解决方案

1. 核心问题定位

从异常信息可以看出,你获取的HTTP响应字节数组实际是被双引号包裹的转义字符串,而非直接的JSON对象。比如异常里显示的Source内容:

(byte[])"{\"Code\":\"200\",\"Msg\":\"\",\"Id\":20147,...}"

这意味着服务端返回的不是纯JSON,而是把JSON作为字符串返回(外层多了双引号,内部JSON字符被转义)。这才是导致Jackson/Gson报错的根本原因,和Msg字段的空字符串无关。

2. 修复步骤

方式一:手动处理转义字符串

先将字节数组转为字符串,去除外层的双引号并反转义,再反序列化为目标类:

ObjectMapper mapper = new ObjectMapper();
byte[] byteResponse = httpResponse.getEntity().getContent().readAllBytes();
// 去除首尾双引号,反转义JSON字符
String jsonStr = new String(byteResponse).replaceAll("^\"|\"$", "").replace("\\\\", "\\");
MatchingResponse response = mapper.readValue(jsonStr, MatchingResponse.class);

方式二:利用Jackson嵌套解析

先把外层字符串解析出来,再将内部内容转成目标类:

ObjectMapper mapper = new ObjectMapper();
byte[] byteResponse = httpResponse.getEntity().getContent().readAllBytes();
// 先读取外层字符串,再解析内部JSON
String wrappedJson = mapper.readValue(byteResponse, String.class);
MatchingResponse response = mapper.readValue(wrappedJson, MatchingResponse.class);

3. 空字符串字段处理(可选)

如果后续需要将空字符串转为null,不需要启用ACCEPT_EMPTY_STRING_AS_NULL_OBJECT(该配置针对对象类型,不适用于String),可以通过以下两种方式处理:

局部字段配置

给目标字段添加注解:

@JsonProperty(value = "Msg")
@JsonSetter(nulls = Nulls.AS_NULL) // 空字符串转null
private String message;

全局配置

通过自定义反序列化器实现全局空字符串转null:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(String.class, new JsonDeserializer<String>() {
    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String value = p.getValueAsString();
        return value == null || value.isEmpty() ? null : value;
    }
});
mapper.registerModule(module);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:54:50