前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 使用Jackson处理json 字符串值反序列化类型为集合时的报错处理 单个值自动转集合

Java 使用Jackson处理json 字符串值反序列化类型为集合时的报错处理 单个值自动转集合

作者头像
heasy3
发布2021-03-04 10:53:21
2.8K0
发布2021-03-04 10:53:21
举报

在处理Json字符串时 有时会遇到一种情况:

JSON字符串中的某一项的值是字符串类型,但想要反序列化为一个集合类型

举例: {"i":1,"list":"astr","str":"em"} 这样一个字符串 想要反序列化为如下的一个类 可以预见的在转换到list时会抛出如下异常

代码语言:javascript
复制
public class Po {

    private Integer i;

    private List<String> list;

    private String str;

}

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'XXX': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')

jackson在发现目标类型是list 但当前字符没有[ 这样的集合开始标志 就会抛出转换失败异常。

解决办法就是在使用之前 为objectMapper增加一项自定义的错误处理器,并在处理这个错误时将list 实例化,将对应的值加入该list

代码:

代码语言:javascript
复制
/**
 * 当json字符串中值为string类型 并无[]符号,且要反序列化为list时 使用该配置解决报错
 *
 * @author heasy
 **/
public class MyDeserializationProblemHandler extends DeserializationProblemHandler {

    @Override
    public Object handleUnexpectedToken(DeserializationContext ctxt, JavaType targetType, JsonToken token, JsonParser parser, String failureMsg) throws IOException {
        //处理json字符串 转 目标为数组 元素为字符串的情况
        if (token == JsonToken.VALUE_STRING && targetType.isCollectionLikeType()) {
            return deserializeString(targetType, parser);
        }
        //处理单个json对象 转 目标为数组 且元素为对象的情况
        if (token == JsonToken.START_OBJECT && targetType.isCollectionLikeType()) {
            return deserializeObject(targetType, parser);
        }
        return super.handleUnexpectedToken(ctxt, targetType, token, parser, failureMsg);
    }


    private Object deserializeObject(JavaType targetType, JsonParser parser) throws IOException {
        List<Object> list = new ArrayList<>(1);
        final Class<?> rawClass = targetType.getContentType().getRawClass();
        final Object o = ReflectUtil.newInstanceIfPossible(rawClass);
        while (parser.getCurrentToken() != JsonToken.END_OBJECT) {
            if (parser.getText().equals(JsonToken.START_OBJECT.asString())) {
                parser.nextToken();
                continue;
            }
            String field = parser.getText();
            parser.nextToken();
            String value = parser.getText();
            if (ReflectUtil.hasField(rawClass, field)) {
                ReflectUtil.setFieldValue(o, field, value);
            }
            parser.nextToken();
        }
        list.add(o);
        return list;
    }

    private Object deserializeString(JavaType listType, JsonParser parser) throws IOException {
        String[] values = parser.getText().split(",");

        JavaType itemType = listType.getContentType();

        List<Object> result = new ArrayList<>(values.length);
        for (String value : values) {
            final String json = "\"" + value.trim() + "\"";
            final Object o = JsonUtil.fromJson(json, itemType);
            result.add(o);
        }

        return result;
    }


}

除了简单字符串转list,还可以处理object的json 转object对应list 这里用到了反射,工具类使用的是hutool的。如果不需要去掉对应判断即可

然后将这个错误处理器配置到你使用的objectmapper中即可

代码语言:javascript
复制
objectMapper.addHandler(new MyDeserializationProblemHandler());
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-02-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档