最近在对接其他系统的时候,经常出现让人特别无语的情况。研发给的文档中明确指明了返回的数据中某个字段类型是数组,但返回的数据有可能是对象,也可能是空串,造成反序列化失败。
研发给的文档中,返回json
示例如下:
{
"cluster": [
"id": "1",
...
]
}
于是我建立了下面所示的dto
对象来进行接收:
@Data
public class ClusterListDTO implements Serializable {
private List<ClusterDTO> cluster;
}
一切都很正常,可用了一段时间,发现问题了。。。文档中虽然明确说明了cluster字段是一个数组,但却没有说——如果数组的长度为1,则会返回一个对象,也就是说,上面的代码,在cluster
长度为1的情况下,返回的数据其实是下面这样的
{
"cluster": {
"id": "1",
...
}
}
于是就出现了这样的错误:
JSON parse error: Cannot deserialize instance of `java.util.ArrayList<com.xxx.cluster.dto.ClusterDTO>` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList<com.xxx.cluster.dto.ClusterDTO>` out of START_OBJECT token
为了避免修改ClusterListDTO
结构对现有业务造成影响,我想到的方案是修改其cluster
字段的反序列化方式,直接将返回的json
中的cluster
字段转为list
即可,如下:
@Data
public class ClusterListDTO implements Serializable {
/**
* 集群列表
*/
@JsonDeserialize(using = ClusterDeserializer.class)
private List<ClusterDTO> cluster;
/**
* 加这个反序列化解析器,目的在于研发返回的数据中cluster节点不一定就是列表,也可能是一个对象
*/
static class ClusterDeserializer extends JsonDeserializer<List<ClusterDTO>> {
public ClusterDeserializer() {
}
@Override
public List<ClusterDTO> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
List<ClusterDTO> list = new ArrayList<>();
try {
// 不能太过相信研发的文档,有同事试过,有的接口虽指明了是list,但可能会返回空串。。。
if (node instanceof TextNode && StringUtils.isBlank(node.textValue())) {
return list;
} else if (node.isArray()) {
return JacksonUtils.json2GenericObject(node.toString(), new TypeReference<List<ClusterDTO>>() {
});
} else if (node.isObject()) {
ClusterDTO dto = JacksonUtils.json2GenericObject(node.toString(), new TypeReference<ClusterDTO>() {
});
list.add(dto);
return list;
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
@Override
public List<ClusterDTO> getNullValue(DeserializationContext ctx) {
return new ArrayList<>();
}
}
}
JacksonUtils
工具类地址:工具类-JacksonUtils
总结:不能太相信别人写的文档,除非你看过源码。