使用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. UVaLive 7456 Least Crucial Node (并查集+暴力 或者 求割点)

    题意:求标号最小的最大割点.(删除该点后,指定点#sink能到达的点数减少最多). 析:由于不知道要去掉哪个结点,又因为只有100个结点,所以我们考虑用一个暴力,把所有的结点都去一次,然后用并查集去判 ...

  2. 五个demo案例带你学习PHP反序列化漏洞

    一直想研究下php反序列化漏洞,花了几天时间做了个简单的了解..写篇文章记录下. 直白点就是围绕着serialize和unserialize两个函数. 一个用于序列化,一个用于反序列化. 我们通常把字 ...

  3. SVG新手入门

    特点 矢量图 属性:形状的参数(都没有单位) 添加事件跟html一样 修改样式跟html一样 属性操作: setAttribute/getAttribute 图形 <svg width=&quo ...

  4. tomcat复习

    javaEE 服务器: java企业版服务器:是一个标准 BS/CS: 1> CS: client/Server 优点:易操作性比较高 缺点:客户端需要升级维护. 2> BS: Brows ...

  5. redis查数据

    1 连接服务 [root@redis1-20 ~]# telnet 127.0.0.1 6380 Trying 127.0.0.1... Connected to 127.0.0.1. Escape ...

  6. python之使用request模块发送post和get请求

    import requestsimport json #发送get请求并得到结果# url = 'http://api.nnzhp.cn/api/user/stu_info?stu_name=小黑马 ...

  7. bzoj 4909 [Sdoi2017]龙与地下城

    题面 https://www.lydsy.com/JudgeOnline/problem.php?id=4909 题解 目前为止仅仅在LOJ上A掉这道题(Loj真快!) 当然不是标准做法 显然我们只要 ...

  8. python_8(模块)

    第1章 模块 1.1 概述 1.2 模块的分类 1.2.1 内置模块 1.2.2 扩展模块 1.2.3 模块安装 1.2.4 自定义模块第2章 模块之内置模块 2.1 collections模块 2. ...

  9. android开发学习 ------- json数据与实体类之间的相互转换

    在网络请求的时候,会返回给我们实体类,我们需要将实体类转化为json字符串,方便处理数据: 有时候也会将json数据转换为实体类. 在Android Studio中,json要互相转换,需要用到gso ...

  10. JavaScript整理

    JavaScript是脚本语言 常用对话框: alert()——警告对话框,作用是弹出一个警告对话框 confirm()——带确定和取消按钮,返回True或false prompt()——弹出一个可以 ...