闲碎记事本 闲碎记事本
首页
  • JAVA
  • Cloudflare
  • 学完再改一遍UI
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

YAN

我要偷偷记录...
首页
  • JAVA
  • Cloudflare
  • 学完再改一遍UI
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • java

    • SpringBoot

    • SpringSecurity

    • MybatisPlus

    • Netty

    • sip

    • 其他

      • MDC 使用
      • 位运算
      • RedisMQ实现
      • 自定义枚举序列化
      • Mybatis使用自定义枚举
      • Jackson反序列化泛型注意点
        • 敏感词过滤算法
        • 线程
        • 并发学习
        • jni使用
        • 关于注释
        • 为什么一个Byte用两个16进制表示
        • JAVA获取系统信息
        • 对extends和super的理解
        • JAVA系统API
        • java探针初探
        • JAVA获取USB信息
        • HashMap初探
        • JAVA远程调试
        • 初探webflux
        • SSE示例
    • linux

    • docker

    • redis

    • nginx

    • mysql

    • 其他

    • 环境搭建

    • 知识库
    • java
    • 其他
    Yan
    2023-03-17
    目录

    Jackson反序列化泛型注意点

    关于Jackson对复杂类型数据反序列化时,泛型对象<T>被转换为 LinkHashMap

    代码如下:

    先贴一段测试代码

    
        @Test
        public void json(){
            String jsonStr = "{"code":0,"subcode":0,"message":"ok","data":{"hostuin":914038622,"encrypt_uin":"NKcPoeoF7w-A","hostname":"YAN","totoal":7,"disslist":[{"diss_name":"QZone背景音乐","diss_cover":"http://y.gtimg.cn/mediastyle/y/img/cover_qzone_130.jpg","song_cnt":5,"listen_num":0,"dirid":205,"tid":0,"dir_show":0},{"diss_name":"搞错了,再来","diss_cover":"http://y.gtimg.cn/music/photo_new/T002R300x300M000000wjiaZ0Q68Vt.jpg?n=1","song_cnt":9,"listen_num":87,"dirid":25,"tid":8445417748,"dir_show":1},{"diss_name":"QQ里的网易云","diss_cover":"http://y.gtimg.cn/music/photo_new/T002R300x300M0000044tjcU3HYRUt.jpg?n=1","song_cnt":7,"listen_num":256,"dirid":23,"tid":8445412062,"dir_show":1},{"diss_name":"哦哦哦哦","diss_cover":"http://y.gtimg.cn/music/photo_new/T002R300x300M0000019DOaT2CE0OG.jpg?n=1","song_cnt":10,"listen_num":94,"dirid":22,"tid":8445391399,"dir_show":1},{"diss_name":"睡觉了","diss_cover":"http://y.gtimg.cn/music/photo_new/T002R300x300M000001HM2km2K4GUv.jpg?n=1","song_cnt":9,"listen_num":29,"dirid":1,"tid":8445382323,"dir_show":1},{"diss_name":"惊艳了时光","diss_cover":"http://qpic.y.qq.com/music_cover/T76450IyeJNdibl3a2PvIRDo2zFwbR8L1g2icGu8GfgxKabkyKTVMveg/300?n=1","song_cnt":11,"listen_num":2227,"dirid":17,"tid":8054843490,"dir_show":1},{"diss_name":"1楼选亚索","diss_cover":"http://qpic.y.qq.com/music_cover/T76450IyeJNdibl3a2PvIRAN81k5hQloWCzsnQNE298kGWfqQG7WCmQ/300?n=1","song_cnt":12,"listen_num":550,"dirid":13,"tid":1436210735,"dir_show":1}]}}";
            ApiResp<SongListResp> resp1 = JsonUtil.toResp(jsonStr, new TypeReference<>() {});
            ApiResp<SongListResp> resp2 = JsonUtil.toBean(jsonStr, new TypeReference<>() {});
            ApiResp<SongListResp> resp3 = JsonUtil.toBean(jsonStr, ApiResp.class);
            
            SongListResp data1 = resp1.getData();
            SongListResp data2 = resp2.getData();
            SongListResp data3 = resp3.getData();
        }
    
    

    运行结果

    测试结果

    可以看到 resp3.data的 类型是LinkHashMap 而并非指定的 SongListResp 所以 resp3.getData() 将会报错

    而 resp1 resp2 则没有这个问题,因为通过new TypeReference<>() {} 指定了泛型类型

    resp1 不同点在于 resp2

    resp1是JsonUtil.toResp()的结果,内部指定了返回类型ApiResp<T>

    resp2 是JsonUtil.toBean()的结果,放回泛型为T,所以在不做强转的情况下,返回的是Object

    Object resp2 = JsonUtil.toBean(jsonStr, new TypeReference<>() {});
    

    # 以下为此处用到的JAVA类

    # JsonUtil

    @Slf4j
    public class JsonUtil {
    
        private static final ObjectMapper OBJECT_MAPPER;
    
    
        static {
            OBJECT_MAPPER = new ObjectMapper();
        }
    
    
        /**
         * 装换成一个支持响应的 Resp
         * @param jsonStr json字符串
         * @param type 想要转换的复杂类型
         * @return  ApiResp类型为 泛型为 <T> 的对象
         * @param <T> 指定泛型
         */
        public static <T> ApiResp<T> toResp(String jsonStr,TypeReference<ApiResp<T>> type){
            return toBean(jsonStr, type);
        }
    
        /**
         * 装换成一个复杂 bean
         * @param jsonStr json字符串
         * @param type 想要转换的复杂类型
         * @return 泛型 T 对象
         * @param <T> 指定泛型
         */
        public static <T> T toBean(String jsonStr,TypeReference<T> type){
            Assert.hasText(jsonStr,"序列化字符串不能为空");
            try {
                return OBJECT_MAPPER.readValue(jsonStr, type);
            } catch (JsonProcessingException e) {
                log.error("JSON字符串反序列化失败",e);
                throw new RuntimeException("JSON字符串反序列化失败");
            }
        }
    
        /**
         * 装换成一个 简单bean
         * @param jsonStr json字符串
         * @param type 想要转换的Classs
         * @return 泛型 T 对象
         * @param <T> 指定泛型
         */
        public static <T> T toBean(String jsonStr,Class<T> type){
            Assert.hasText(jsonStr,"序列化字符串不能为空");
            try {
                return OBJECT_MAPPER.readValue(jsonStr, type);
            } catch (JsonProcessingException e) {
                log.error("JSON字符串反序列化失败",e);
                throw new RuntimeException("JSON字符串反序列化失败");
            }
        }
    
    }
    

    # 实体 ApiResp

    @Data
    @Accessors(chain = true)
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class ApiResp<T> {
    
        @JsonProperty("code")
        private String code;
    
        @JsonProperty("data")
        private T data;
    
    }
    

    # 实体 SongListResp

    @Data
    @Accessors(chain = true)
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class SongListResp {
    
    
        @JsonProperty("hostuin")
        private String hostuin;
    
        @JsonProperty("disslist")
        private List<DisslistDTO> disslist;
    
        @Data
        @Accessors(chain = true)
        @JsonIgnoreProperties(ignoreUnknown = true)
        public static class DisslistDTO {
    
            //以下属性省略
        }
    
    }
    
    
    上次更新: 2025/05/14, 01:34:05
    Mybatis使用自定义枚举
    敏感词过滤算法

    ← Mybatis使用自定义枚举 敏感词过滤算法→

    最近更新
    01
    Caddy操作指南
    04-25
    02
    Swap空间
    04-22
    03
    Alist使用
    04-21
    更多文章>
    Theme by Vdoing | Copyright © 2022-2025 YAN | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式