• RestTemplate Hashmap变为LinkedHashMap源码解读


    使用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)
     
  • 相关阅读:
    BSF、BSR: 位扫描指令
    驱动学习4
    DDK Build的DIRS和SOURCE文件
    sql语句中的字符串拼接
    delphi中WMI的使用(二)
    delphi中WMI的使用(一)
    WPF中实现砖块拖动的方法(2)
    HttpWebRequest中UserAgent的使用
    获取本机外网IP相关
    WPF中实现砖块拖动的方法(1)
  • 原文地址:https://www.cnblogs.com/gqymy/p/11053251.html
Copyright © 2020-2023  润新知