使用restTemplate远程调用服务,正常应该接收List<HashMap>数据,但实际却是List<LikedHashMap>经过不断地debug,终于找到了数据被转换成LinkedHashMap的方法,下面我将这个可恶的方法贴出来并解读(解决方式在另一篇https://www.cnblogs.com/gqymy/p/11047327.html)
 
包 com.fasterxml.jackson.databind.deser.std;
 
类: UntypedObjectDeserializer
如果需要绑定“未知”类型的内容,则使用反序列化器实现;声明为基本对象的东西(显式地,或由于类型擦除)。如果是这样,“自然”映射用于将JSON值转换为它们的自然Java对象匹配:JSON数组转换为Java列表(或者,如果配置了object []), JSON对象转换为映射,数字转换为数字,布尔值转换为布尔值,字符串转换为字符串(以及null转换为null)
 
方法: mapObject
方法调用,以将JSON对象映射到Java值
 
//JsonParser 定义用于读取JSON内容的公共API的基类。实例是使用JsonFactory实例的工厂方法创建的
protected Object mapObject(JsonParser p, DeserializationContext ctxt) throws IOException {
    //访问器,查找当前指向哪个令牌解析器(如果有的话);如果没有,则返回null。如果返回值是非空的,则与令牌关联的数据可以通过其他访问器方法获得
    JsonToken t = p.getCurrentToken();
    String key1;
    if (t == JsonToken.START_OBJECT) {
        //该方法获取下一个令牌(就像调用nextToken()一样)并验证它是否是JsonToken。具有指定名称的FIELD_NAME,并返回该比较的结果。具体方法看下方截图
        key1 = p.nextFieldName();
    } else if (t == JsonToken.FIELD_NAME) {
        //方法来获取与当前令牌关联的名称:for JsonToken。FIELD_NAMEs将与getText()返回的内容相同;对于字段值,它将在字段名之前;对于其他值(数组值、根级值)为null
        key1 = p.getCurrentName();
    } else {
        if (t != JsonToken.END_OBJECT) {
            //2.0API没有此方法,懒得读了
            return ctxt.handleUnexpectedToken(this.handledType(), p);
        }
        key1 = null;
    }
    if (key1 == null) {
        //创建一个容量为2的linkedhashmap
        return new LinkedHashMap(2);
    } else {
        //迭代方法,该方法将充分推进流,以确定下一个令牌的类型,即值类型(包括JSON数组和对象开始/结束标记)。或者换句话说,nextToken()将被调用一次,如果JsonToken。返回                  FIELD_NAME,这是获取字段值的另一个时间。方法对于遍历JSON对象的值条目最有用;当解析器指向值时,通过调用getCurrentName(),字段名仍然可用
            个人觉得类似于迭代器的next()方法
        p.nextToken();
        //反序列化json
        Object value1 = this.deserialize(p, ctxt);
        String key2 = p.nextFieldName();
        if (key2 == null) {
            LinkedHashMap<String, Object> result = new LinkedHashMap(2);
            result.put(key1, value1);
            return result;
        } else {
            p.nextToken();
            Object value2 = this.deserialize(p, ctxt);
            String key = p.nextFieldName();
            LinkedHashMap result;
            if (key == null) {
                result = new LinkedHashMap(4);
                result.put(key1, value1);
                result.put(key2, value2);
                return result;
            } else {
                result = new LinkedHashMap();
                result.put(key1, value1);
                result.put(key2, value2);
                //在这里进行对JsonParser的循环并装进LinkedHashMap中
                do {
                    p.nextToken();
                    result.put(key, this.deserialize(p, ctxt));
                } while((key = p.nextFieldName()) != null);
                return result;
            }
        }
    }
}
 
 
下面是记录的执行方法:
RestTemplate -> postForObject()
RestTemplate -> execute(413)
RestTemplate -> doExecute(444)
HttpMessageConverterExtractor -> extractData(65行)
AbstractJackson2HttpMessageConverter -> read()
AbstractJackson2HttpMessageConverter -> readJavaType()
ObjectMapper -> readValue()
ObjectMapper -> _readMapAndClose(1197行 result = deser.deserialize(p, ctxt);)
CollectionDeserializer -> deserialize(115行)
CollectionDeserializer -> deserialize(134行  执行while循环  else if (typeDeser == null)判断)
UntypedObjectDeserializer -> deserialize(走case 5)
 

RestTemplate Hashmap变为LinkedHashMap源码解读的更多相关文章

  1. LRU算法实现,HashMap与LinkedHashMap源码的部分总结

    关于HashMap与LinkedHashMap源码的一些总结 JDK1.8之后的HashMap底层结构中,在数组(Node<K,V> table)长度大于64的时候且链表(依然是Node) ...

  2. HashTable、HashMap与ConCurrentHashMap源码解读

    HashMap 的数据结构 ​ hashMap 初始的数据结构如下图所示,内部维护一个数组,然后数组上维护一个单链表,有个形象的比喻就是想挂钩一样,数组脚标一样的,一个一个的节点往下挂. ​ 我们可以 ...

  3. LinkedHashMap源码解读

    1. 前言 还是从面试中来,到面试中去.面试官在面试 Redis 的时候经常会问到,Redis 的 LRU 是如何实现的?如果让你实现 LRU 算法,你会怎么实现呢?除了用现有的结构 LinkedHa ...

  4. jdk1.8.0_45源码解读——HashMap的实现

    jdk1.8.0_45源码解读——HashMap的实现 一.HashMap概述 HashMap是基于哈希表的Map接口实现的,此实现提供所有可选的映射操作.存储的是<key,value>对 ...

  5. java jdk 中HashMap的源码解读

    HashMap是我们在日常写代码时最常用到的一个数据结构,它为我们提供key-value形式的数据存储.同时,它的查询,插入效率都非常高. 在之前的排序算法总结里面里,我大致学习了HashMap的实现 ...

  6. jdk1.8.0_45源码解读——HashSet的实现

    jdk1.8.0_45源码解读——HashSet的实现 一.HashSet概述 HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.主要具有以下的特点: 不保证set的迭代顺 ...

  7. 并发-HashMap和HashTable源码分析

    HashMap和HashTable源码分析 参考: https://blog.csdn.net/luanlouis/article/details/41576373 http://www.cnblog ...

  8. JDK容器类Map源码解读

    java.util.Map接口是JDK1.2开始提供的一个基于键值对的散列表接口,其设计的初衷是为了替换JDK1.0中的java.util.Dictionary抽象类.Dictionary是JDK最初 ...

  9. JDK容器类List,Set,Queue源码解读

    List,Set,Queue都是继承Collection接口的单列集合接口.List常用的实现主要有ArrayList,LinkedList,List中的数据是有序可重复的.Set常用的实现主要是Ha ...

随机推荐

  1. error the @annotation pointcut expression is only supported at Java 5

    eclipse搭建环境后报错 the pointcut is supported at Java 5 错误意思大致是:注释切入点表达式只支持在Java 5版本以上,我就纳闷了我安装的是jdk1.8啊, ...

  2. Hadoop 三大调度器源码分析及编写自己的调度器

    如要转载,请注上作者和出处.  由于能力有限,如有错误,请大家指正. 须知: 我们下载的是hadoop-2.7.3-src 源码. 这个版本默认调度器是Capacity调度器. 在2.0.2-alph ...

  3. In-App Purchase Programming Guide----(五) ----Delivering Products

    Delivering Products In the final part of the purchase process, your app waits for the App Store to p ...

  4. kubeadm安装Kubernetes13.1集群-三

    环境: master: 192.168.3.100 node01: 192.168.3.101 node02: 192.168.3.102 关闭所有主机防火墙,selinux: 配置主机互信: mas ...

  5. 1-1 课程导学 & 1-2 项目需求分析,技术分解.

    1-1 课程导学 1-2 项目需求分析,技术分解. 要有一定的dart基础,了解安卓和ios的一些普通的开发

  6. Vue-i18n实现语言切换

    方法1 Vue — i18n 国际化 全局配置 安 装 1.直接引入js文件 <script src="https://unpkg.com/vue/dist/vue.js"& ...

  7. SCUT - 249 - A piece of Cake - 组合数学

    https://scut.online/contest/25/I 由结论:d维物体切n刀分成的部分=sum(C(n,0)~C(n,d)),直接算就行了.

  8. 3dmax学习资料记录

    max2015 官方文档 http://help.autodesk.com/view/3DSMAX/2015/CHS/?guid=GUID-D015E335-EFB3-43BF-AB27-C3CB09 ...

  9. linux 问题二 查看系统是32位还是64位

    方法: 1.uname -a 2.uname -m 3.file /sbin/init 4.arch 5.Settings -> Details 说明: 1. i386 适用于intel和AMD ...

  10. web前端图片预加载

    是什么? 浏览器会缓存静态资源(hmtl/css/img等).图片预加载就是让浏览器提前缓存图片,提升用户体验. 浏览器什么情况下会下载图片? 1,解析到html中img的src属性的时候 2,解析到 ...