将格式错误的JSON数组字符串转换为Java对象的方法
我从API拿到了一段格式有问题的JSON数组字符串,具体是ResponseMsg属性值的左方括号前多了个双引号,导致整个JSON结构不合法:
[{"ResponseCode":1,"ResponseMsg":"[{"Code":"CA2305181","Message":"Processed successfully"}]"}]
我试过用Jackson解析,代码如下:
ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new ResponseNameStrategy()); Response[] response = mapper.readValue(strOutput1, Response[].class);
结果报错:Error: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token
也尝试过Gson解析:
Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE) .create(); Response[] response = gson.fromJson(strOutput1, Response[].class);
报错信息是:Error: Expected BEGIN_ARRAY but was STRING at line 1 column 35 path $[0].ResponseMsg
我查了不少相关问题,但都没解决我的问题。
解决方案思路
因为原始JSON本身是格式不合法的,所以第一步必须先修复这个JSON的格式问题,再进行解析。这里的核心问题是ResponseMsg的值被错误地用双引号包裹成了字符串,实际上它应该是一个JSON数组。
方法一:手动修复字符串(适合固定格式的场景)
如果API返回的错误格式是固定的(比如总是在ResponseMsg的[前多双引号、结尾多双引号),可以先用字符串替换快速修正:
// 修正格式错误:去掉ResponseMsg值前后的多余双引号 String fixedJson = strOutput1.replace("\"[{\"", "[{\"").replace("\"}]\"", "}]"); // 之后再用Jackson或Gson解析修正后的fixedJson
方法二:自定义反序列化器(更灵活的通用方案)
如果错误格式有变化,或者不想依赖硬编码的字符串替换,可以自定义反序列化逻辑,告诉解析器把ResponseMsg的字符串内容当作JSON数组来解析。
用Jackson实现自定义反序列化
假设你的实体类结构是这样的:
public class Response { private int ResponseCode; private List<ResponseDetail> ResponseMsg; // getter、setter、构造方法 } public class ResponseDetail { private String Code; private String Message; // getter、setter、构造方法 }
编写自定义反序列化器:
public class ResponseMsgDeserializer extends JsonDeserializer<List<ResponseDetail>> { @Override public List<ResponseDetail> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 获取ResponseMsg的字符串内容 String msgStr = p.getText(); // 去掉前后多余的双引号 msgStr = msgStr.replaceAll("^\"|\"$", ""); // 将处理后的字符串解析为List ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(msgStr, new TypeReference<List<ResponseDetail>>() {}); } }
然后在Response类的ResponseMsg字段上添加注解,指定使用自定义反序列化器:
public class Response { private int ResponseCode; @JsonDeserialize(using = ResponseMsgDeserializer.class) private List<ResponseDetail> ResponseMsg; // ... }
之后再用Jackson解析原始JSON字符串就能正常工作了。
用Gson实现自定义反序列化
同样基于上述实体类,编写Gson的自定义反序列化器:
public class ResponseMsgDeserializer implements JsonDeserializer<List<ResponseDetail>> { @Override public List<ResponseDetail> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String msgStr = json.getAsString(); // 去掉前后多余的双引号 msgStr = msgStr.replaceAll("^\"|\"$", ""); // 将处理后的字符串解析为List return new Gson().fromJson(msgStr, typeOfT); } }
注册反序列化器后再解析:
Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE) .registerTypeAdapter(new TypeToken<List<ResponseDetail>>(){}.getType(), new ResponseMsgDeserializer()) .create(); Response[] response = gson.fromJson(strOutput1, Response[].class);
内容的提问来源于stack exchange,提问作者A_J

