使用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. 斯坦福CS231n—深度学习与计算机视觉----学习笔记 课时5

    课时5 数据驱动的图像分类方式:K最邻近与线性分类器(下) 在参数化方法中,我们要做的是构造一个函数,输入一张图片,对每一类输出一个数值.对任意一张图片,我们会计算出它到底属于哪一类.这些参数有时候也 ...

  2. Unity局部高效实时阴影的思考和实现

    http://game.ceeger.com/forum/read.php?tid=23305&fid=2 无意间看到一篇文章,说是Unity5 demo中为了实现角色的良好阴影,单独给角色设 ...

  3. python 生成器 generator

    一.生成器定义 通过列表生成表达式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢? ...

  4. python 标准库大全

    python 标准库 文本 string:通用字符串操作 re:正则表达式操作 difflib:差异计算工具 textwrap:文本填充 unicodedata:Unicode字符数据库 string ...

  5. 跟我一起玩Win32开发(22):抓取屏幕

    关于如何拷贝屏幕并保存,这里已经有现成的例子,我也不必去Copy人家了,我一向不喜欢Copy.这里有一个完整的例子,可以看看. http://msdn.microsoft.com/EN-US/libr ...

  6. 根据 目录号 案卷号 用户名 查询 page 中 的条数

    select count(*) from am_b_page a join am_b_entry b on a.entry_id=b.entry_id where b.catalogue_code=' ...

  7. HDU 2227 Find the nondecreasing subsequences dp思想 + 树状数组

    http://acm.hdu.edu.cn/showproblem.php?pid=2227 用dp[i]表示以第i个数为结尾的nondecreasing串有多少个. 那么对于每个a[i] 要去找 & ...

  8. 迭代器———更锋利的C#代码小记(3)

    直接使用yield return关键字通过类似返回值的方式灵活地构造迭代器 public class EmployeeCollection :IEnumerable<Employee> { ...

  9. 自動獲取外網IP并發郵件

    問題: 公司有一Web系統需開放給香港Office公司查詢資料,但最近動態域名需實名認證, 因系統較小型,非公開大範圍使用,所以再認證一域名也沒多大必要, 所以想定時生成一封能查詢外網IP的郵件發送給 ...

  10. AJPFX浅谈Java新手问题之缺少良好的编程习惯

    ★随意地命名 有些新手写程序,当需要定义某个变量名(也可能是函数名.类名.包名等)时,随意地一敲键盘,名字就起好了......若干星期后,碰到某 bug,再来看自己写的代码时,心中暗自嘀咕:“这代码是 ...