记一次接口规范导致的反序列化错误问题

最近在对接其他系统的时候,经常出现让人特别无语的情况。研发给的文档中明确指明了返回的数据中某个字段类型是数组,但返回的数据有可能是对象,也可能是空串,造成反序列化失败。

研发给的文档中,返回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

总结:不能太相信别人写的文档,除非你看过源码。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值