码迷,mamicode.com
首页 > Web开发 > 详细

从fastjson多层泛型嵌套解析,看jdk泛型推断

时间:2019-04-11 19:24:15      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:tcl   md5   这一   click   结果   wired   iter   listt   存在   

  给你一组json数据结构,你把它解析出来到项目中,你会怎么做?

// data1 sample
{
    "code" : "1",
    "msg" : "Success",
    "data" : {
        "userid1" : {
            "name" : "Zhangsan",
            "sex" : "male"
        }
    }
}
// data2 sample
{
    "code" : "1",
    "msg" : "Success",
    "data" : {
        "orderid1" : {
            "address" : "street 1",
            "pay" : "111.0",
            "productId" : "1342546"
        }
    }
}

  首先,code,msg,data 肯定是固定结构,所以可以抽象出一层 data 的变化,可以使用泛型去适应变化;

  其次,data下的数据是 key -> object 的结构,如果直接object表示的话,又不友好了。如果不以object表示,针对不同的object又如何是好?答案是,再抽象一层泛型出来就行了;

  最终的数据结构就是这样: ResponseEntity<T> ---> ResponseEntity<Map<String, T>> , 具体bean就不用写了吧!

其实做这一步的解析,还是容易的。不过,具体怎么做,就不一定了。

  另一个问题,解析这些数据结构,我需要再封装得简单点,因为底层的数据访问步骤都是一样的,我不想重复造轮子!比如,我只需要在最上层转入想要转化的数据结构类型,就可以得到不一样的数据对象!

这个当然很简单,只需要使用泛型方法就行了。简单示例如下:

public class CapitalUtilsTest {

    @Test
    public void testInnerGenericAnalyze() {
        ResponseEntity<Map<String, OrderDetail>> result = parseMoreGenericParams();
        System.out.println("result:" + result);
    }

    private <T> ResponseEntity<Map<String, T>> parseMoreGenericParams() {
        String json = "{\"code\":\"1\",\"msg\":\"Success\",\"data\":{\"orderid1\":{\"address\":\"street 1\",\"pay\":\"111.0\",\"productId\":\"1342546\"}}}";
        return JSONObject.parseObject(json, new TypeReference<ResponseEntity<Map<String, T>>>(){});
    }
}

class ResponseEntity<T> {
    private String code;
    private String msg;
    private T data;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "ResponseEntity{" +
                "code=‘" + code + ‘\‘‘ +
                ", msg=‘" + msg + ‘\‘‘ +
                ", data=" + data +
                ‘}‘;
    }
}

class OrderDetail {
    private String orderId;
    private String address;
    private String productId;

    @Override
    public String toString() {
        return "OrderDetail{" +
                "orderId=‘" + orderId + ‘\‘‘ +
                ", address=‘" + address + ‘\‘‘ +
                ", productId=‘" + productId + ‘\‘‘ +
                ‘}‘;
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }
}

  其中,json的解析,我们选择了fastjson,这其实不重要。

  重要的是,你认为,如上代码能成功达到要求吗???

  不管怎么样,IDE 是不会报错的,编译也是没问题,而且运行无误!

  如上示例的输出结果是:

result:ResponseEntity{code=‘1‘, msg=‘Success‘, data={orderid1={"address":"street 1","productId":"1342546","pay":"111.0"}}}

  输出如上结果,是因为最终 data 结构已经变成了 JsonObject 对象了,所以并没有看 OrderDetail 的信息!

  那么,还有哪里不对?不对在于,你认为的 OrderDetail 信息,其实已经不存在了,此时,你如果直接使用 OrderDetail 的 data , 则必定导致 ClassCastException.

  我们知道,java的泛型是一种语法糖,在编译后就会进行类型擦除。所以,在第二次泛型传递时,我们已经完全不知道其原始类型了。我们直接来看下编译后的代码:

技术图片
Classfile /D:/www.richCash.target.test-classes.com.test.CapitalUtilsTest.class
  Last modified 2019-4-6; size 1959 bytes
  MD5 checksum e8b36dfda241162b15ada875df4345e0
  Compiled from "CapitalUtilsTest"
public class com.test.CapitalUtilsTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #18.#42        // java.lang.Object."<init>":()V
   #2 = Methodref          #17.#43        // com.test.CapitalUtilsTest.parseMoreGenericParams:()Lcom.test.ResponseEntity;
   #3 = Fieldref           #44.#45        // java.lang.System.out:Ljava.io.PrintStream;
   #4 = Class              #46            // java.lang.StringBuilder
   #5 = Methodref          #4.#42         // java.lang.StringBuilder."<init>":()V
   #6 = String             #47            // result:
   #7 = Methodref          #4.#48         // java.lang.StringBuilder.append:(Ljava.lang.String;)Ljava.lang.StringBuilder;
   #8 = Methodref          #4.#49         // java.lang.StringBuilder.append:(Ljava.lang.Object;)Ljava.lang.StringBuilder;
   #9 = Methodref          #4.#50         // java.lang.StringBuilder.toString:()Ljava.lang.String;
  #10 = Methodref          #51.#52        // java.io.PrintStream.println:(Ljava.lang.String;)V
  #11 = String             #53            // {\"code\":\"1\",\"msg\":\"Success\",\"data\":{\"orderid1\":{\"address\":\"street 1\",\"pay\":\"111.0\",\"productId\":\"1342546\"}}}
  #12 = Class              #54            // com.test.CapitalUtilsTest$1
  #13 = Methodref          #12.#55        // com.test.CapitalUtilsTest$1."<init>":(Lcom.test.CapitalUtilsTest;)V
  #14 = Class              #56            // com.alibaba.fastjson.parser.Feature
  #15 = Methodref          #57.#58        // com.alibaba.fastjson.JSONObject.parseObject:(Ljava.lang.String;Lcom.alibaba.fastjson.TypeReference;[Lcom.alibaba.fastjson.parser.Feature;)Ljava.lang.Object;
  #16 = Class              #59            // com.test.ResponseEntity
  #17 = Class              #60            // com.test.CapitalUtilsTest
  #18 = Class              #61            // java.lang.Object
  #19 = Utf8               InnerClasses
  #20 = Utf8               <init>
  #21 = Utf8               ()V
  #22 = Utf8               Code
  #23 = Utf8               LineNumberTable
  #24 = Utf8               LocalVariableTable
  #25 = Utf8               this
  #26 = Utf8               Lcom.test.CapitalUtilsTest;
  #27 = Utf8               testInnerGenericAnalyze
  #28 = Utf8               result
  #29 = Utf8               Lcom.test.ResponseEntity;
  #30 = Utf8               LocalVariableTypeTable
  #31 = Utf8               Lcom.test.ResponseEntity<Ljava.util.Map<Ljava.lang.String;Lcom.test.OrderDetail;>;>;
  #32 = Utf8               RuntimeVisibleAnnotations
  #33 = Utf8               Lorg.junit.Test;
  #34 = Utf8               parseMoreGenericParams
  #35 = Utf8               ()Lcom.test.ResponseEntity;
  #36 = Utf8               json
  #37 = Utf8               Ljava.lang.String;
  #38 = Utf8               Signature
  #39 = Utf8               <T:Ljava.lang.Object;>()Lcom.test.ResponseEntity<Ljava.util.Map<Ljava.lang.String;TT;>;>;
  #40 = Utf8               SourceFile
  #41 = Utf8               CapitalUtilsTest
  #42 = NameAndType        #20:#21        // "<init>":()V
  #43 = NameAndType        #34:#35        // parseMoreGenericParams:()Lcom.test.ResponseEntity;
  #44 = Class              #62            // java.lang.System
  #45 = NameAndType        #63:#64        // out:Ljava.io.PrintStream;
  #46 = Utf8               java.lang.StringBuilder
  #47 = Utf8               result:
  #48 = NameAndType        #65:#66        // append:(Ljava.lang.String;)Ljava.lang.StringBuilder;
  #49 = NameAndType        #65:#67        // append:(Ljava.lang.Object;)Ljava.lang.StringBuilder;
  #50 = NameAndType        #68:#69        // toString:()Ljava.lang.String;
  #51 = Class              #70            // java.io.PrintStream
  #52 = NameAndType        #71:#72        // println:(Ljava.lang.String;)V
  #53 = Utf8               {\"code\":\"1\",\"msg\":\"Success\",\"data\":{\"orderid1\":{\"address\":\"street 1\",\"pay\":\"111.0\",\"productId\":\"1342546\"}}}
  #54 = Utf8               com.test.CapitalUtilsTest$1
  #55 = NameAndType        #20:#73        // "<init>":(Lcom.test.CapitalUtilsTest;)V
  #56 = Utf8               com.alibaba.fastjson.parser.Feature
  #57 = Class              #74            // com.alibaba.fastjson.JSONObject
  #58 = NameAndType        #75:#76        // parseObject:(Ljava.lang.String;Lcom.alibaba.fastjson.TypeReference;[Lcom.alibaba.fastjson.parser.Feature;)Ljava.lang.Object;
  #59 = Utf8               com.test.ResponseEntity
  #60 = Utf8               com.test.CapitalUtilsTest
  #61 = Utf8               java.lang.Object
  #62 = Utf8               java.lang.System
  #63 = Utf8               out
  #64 = Utf8               Ljava.io.PrintStream;
  #65 = Utf8               append
  #66 = Utf8               (Ljava.lang.String;)Ljava.lang.StringBuilder;
  #67 = Utf8               (Ljava.lang.Object;)Ljava.lang.StringBuilder;
  #68 = Utf8               toString
  #69 = Utf8               ()Ljava.lang.String;
  #70 = Utf8               java.io.PrintStream
  #71 = Utf8               println
  #72 = Utf8               (Ljava.lang.String;)V
  #73 = Utf8               (Lcom.test.CapitalUtilsTest;)V
  #74 = Utf8               com.alibaba.fastjson.JSONObject
  #75 = Utf8               parseObject
  #76 = Utf8               (Ljava.lang.String;Lcom.alibaba.fastjson.TypeReference;[Lcom.alibaba.fastjson.parser.Feature;)Ljava.lang.Object;
{
  public com.test.CapitalUtilsTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java.lang.Object."<init>":()V
         4: return
      LineNumberTable:
        line 15: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom.test.CapitalUtilsTest;

  public void testInnerGenericAnalyze();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=1
         0: aload_0
         1: invokespecial #2                  // Method parseMoreGenericParams:()Lcom.test.ResponseEntity;
         4: astore_1
         5: getstatic     #3                  // Field java.lang.System.out:Ljava.io.PrintStream;
         8: new           #4                  // class java.lang.StringBuilder
        11: dup
        12: invokespecial #5                  // Method java.lang.StringBuilder."<init>":()V
        15: ldc           #6                  // String result:
        17: invokevirtual #7                  // Method java.lang.StringBuilder.append:(Ljava.lang.String;)Ljava.lang.StringBuilder;
        20: aload_1
        21: invokevirtual #8                  // Method java.lang.StringBuilder.append:(Ljava.lang.Object;)Ljava.lang.StringBuilder;
        24: invokevirtual #9                  // Method java.lang.StringBuilder.toString:()Ljava.lang.String;
        27: invokevirtual #10                 // Method java.io.PrintStream.println:(Ljava.lang.String;)V
        30: return
      LineNumberTable:
        line 19: 0
        line 20: 5
        line 21: 30
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      31     0  this   Lcom.test.CapitalUtilsTest;
            5      26     1 result   Lcom.test.ResponseEntity;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            5      26     1 result   Lcom.test.ResponseEntity<Ljava.util.Map<Ljava.lang.String;Lcom.test.OrderDetail;>;>;
    RuntimeVisibleAnnotations:
      0: #33()

  private <T extends java.lang.Object> com.test.ResponseEntity<java.util.Map<java.lang.String, T>> parseMoreGenericParams();
    descriptor: ()Lcom.test.ResponseEntity;
    flags: ACC_PRIVATE
    Code:
      stack=4, locals=2, args_size=1
         0: ldc           #11                 // String {\"code\":\"1\",\"msg\":\"Success\",\"data\":{\"orderid1\":{\"address\":\"street 1\",\"pay\":\"111.0\",\"productId\":\"1342546\"}}}
         2: astore_1
         3: aload_1
         4: new           #12                 // class com.test.CapitalUtilsTest$1
         7: dup
         8: aload_0
         9: invokespecial #13                 // Method com.test.CapitalUtilsTest$1."<init>":(Lcom.test.CapitalUtilsTest;)V
        12: iconst_0
        13: anewarray     #14                 // class com.alibaba.fastjson.parser.Feature
        16: invokestatic  #15                 // Method com.alibaba.fastjson.JSONObject.parseObject:(Ljava.lang.String;Lcom.alibaba.fastjson.TypeReference;[Lcom.alibaba.fastjson.parser.Feature;)Ljava.lang.Object;
        19: checkcast     #16                 // class com.test.ResponseEntity
        22: areturn
      LineNumberTable:
        line 24: 0
        line 25: 3
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      23     0  this   Lcom.test.CapitalUtilsTest;
            3      20     1  json   Ljava.lang.String;
    Signature: #39                          // <T:Ljava.lang.Object;>()Lcom.test.ResponseEntity<Ljava.util.Map<Ljava.lang.String;TT;>;>;
}
SourceFile: "CapitalUtilsTest"
InnerClasses:
     #12; //class com.test.CapitalUtilsTest$1
View Code

  很神奇,泛型居然还在!!! 其实这只在字节码保留的 signature, 实际在运行时已经不在了!

  所以,第二次封装后,只剩下了object了,所以,最终解析出来的 map 的 value 会变成 jsonobject 就不足为奇了。

  这看起来很完美,好像这条路走不通了。那么,我想转换出内部具体类型怎么办?

  我们知道,fastjson 中想要解析泛型,就是通过 new TypeReference<>(){} 来实现的,那为什么它能实现,而我们却不能实现呢?我们先看下 TypeReference 的泛型推断原理吧!

package com.alibaba.fastjson;

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.alibaba.fastjson.util.ParameterizedTypeImpl;
import com.alibaba.fastjson.util.TypeUtils;

/** 
 * Represents a generic type {@code T}. Java doesn‘t yet provide a way to
 * represent generic types, so this class does. Forces clients to create a
 * subclass of this class which enables retrieval the type information even at
 * runtime.
 *
 * <p>For example, to create a type literal for {@code List<String>}, you can
 * create an empty anonymous inner class:
 *
 * <pre>
 * TypeReference&lt;List&lt;String&gt;&gt; list = new TypeReference&lt;List&lt;String&gt;&gt;() {};
 * </pre>
 * This syntax cannot be used to create type literals that have wildcard
 * parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}.
 */
public class TypeReference<T> {
    static ConcurrentMap<Type, Type> classTypeCache
            = new ConcurrentHashMap<Type, Type>(16, 0.75f, 1);

    protected final Type type;

    // 一般情况下,我们使用此默认构造器就足够了
    /**
     * Constructs a new type literal. Derives represented class from type
     * parameter.
     *
     * <p>Clients create an empty anonymous subclass. Doing so embeds the type
     * parameter in the anonymous class‘s type hierarchy so we can reconstitute it
     * at runtime despite erasure.
     */
    protected TypeReference(){
        // 先获取完整的泛型类,从这里可以看出,jdk的泛型虽然是擦除式的,但仍然是有迹可寻的
        // TypeReference<List<String>>
        Type superClass = getClass().getGenericSuperclass();

        // 接着,从完整的类型定义中,取出真正的泛型类型,比如 java.util.List<String>
        Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];

        Type cachedType = classTypeCache.get(type);
        if (cachedType == null) {
            classTypeCache.putIfAbsent(type, type);
            cachedType = classTypeCache.get(type);
        }

        this.type = cachedType;
    }

    /**
     * @since 1.2.9
     * @param actualTypeArguments
     */
    protected TypeReference(Type... actualTypeArguments){
        Class<?> thisClass = this.getClass();
        Type superClass = thisClass.getGenericSuperclass();

        // 先直接获取传入 TypeReference 的泛型信息 ResponseEntity<Map<String, T>>
        ParameterizedType argType = (ParameterizedType) ((ParameterizedType) superClass).getActualTypeArguments()[0];
        // 获取无泛型类 ResponseEntity
        Type rawType = argType.getRawType();
        // 再获取第一层泛型信息, Map<String, T>
        Type[] argTypes = argType.getActualTypeArguments();

        int actualIndex = 0;
        for (int i = 0; i < argTypes.length; ++i) {
            // ParameterizedTypeImpl
            if (argTypes[i] instanceof TypeVariable &&
                    actualIndex < actualTypeArguments.length) {
                argTypes[i] = actualTypeArguments[actualIndex++];
            }
            // fix for openjdk and android env
            if (argTypes[i] instanceof GenericArrayType) {
                argTypes[i] = TypeUtils.checkPrimitiveArray(
                        (GenericArrayType) argTypes[i]);
            }

            // 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
            // 复杂类型都会被解析为 ParameterizedType 类型
            // 而类似于 T 这种泛型,则会被解析为 TypeVariableImpl
            if(argTypes[i] instanceof ParameterizedType) {
                argTypes[i] = handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex);
            }
        }

        // ParameterizedTypeImpl 的 hashCode() 是采用 ownerType + rawType + actualTypeArguments 进行判定的,所以 cache 会有用
        Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
        Type cachedType = classTypeCache.get(key);
        if (cachedType == null) {
            classTypeCache.putIfAbsent(key, key);
            cachedType = classTypeCache.get(key);
        }

        // 放入缓存后返回
        type = cachedType;

    }
    // ParameterizedTypeImpl.equals()
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ParameterizedTypeImpl that = (ParameterizedTypeImpl) o;

        // Probably incorrect - comparing Object[] arrays with Arrays.equals
        if (!Arrays.equals(actualTypeArguments, that.actualTypeArguments)) return false;
        if (ownerType != null ? !ownerType.equals(that.ownerType) : that.ownerType != null) return false;
        return rawType != null ? rawType.equals(that.rawType) : that.rawType == null;

    }
    // ParameterizedTypeImpl.hashCode()
    @Override
    public int hashCode() {
        int result = actualTypeArguments != null ? Arrays.hashCode(actualTypeArguments) : 0;
        result = 31 * result + (ownerType != null ? ownerType.hashCode() : 0);
        result = 31 * result + (rawType != null ? rawType.hashCode() : 0);
        return result;
    }

    // 相当于递归解析
    private Type handlerParameterizedType(ParameterizedType type, Type[] actualTypeArguments, int actualIndex) {
        Class<?> thisClass = this.getClass();
        Type rawType = type.getRawType();
        Type[] argTypes = type.getActualTypeArguments();

        for(int i = 0; i < argTypes.length; ++i) {
            if (argTypes[i] instanceof TypeVariable && actualIndex < actualTypeArguments.length) {
                // 通过位置一一对应。 1. 是 TypeVariable 即是 T 这样的泛型, 如 <T1, T2, T3>, 则传入的构造参数也应该是 (T1, T2, T3), 否则将对应错误
                argTypes[i] = actualTypeArguments[actualIndex++];
            }

            // fix for openjdk and android env
            if (argTypes[i] instanceof GenericArrayType) {
                argTypes[i] = TypeUtils.checkPrimitiveArray(
                        (GenericArrayType) argTypes[i]);
            }

            // 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
            // 多层则递归
            if(argTypes[i] instanceof ParameterizedType) {
                return handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex);
            }
        }

        // 重新 new 一个 ParameterizedTypeImpl 出来返回
        Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
        return key;
    }
    
    /**
     * Gets underlying {@code Type} instance.
     */
    public Type getType() {
        return type;
    }

    // 最开始就会初始化一个 LIST_STRING 的类型备用
    public final static Type LIST_STRING = new TypeReference<List<String>>() {}.getType();
}

  我们很容易想到的,就是在外部结果中,进行循环后,进行类型转换,然后再插入到原始key中。这看起来其实也不坏,但是,你这样反复循环操作,是不是有点耗性能了;另外,我还得写很多重复的代码啊。
  所以,我们还得更优雅的方法吗?当然你可以不用转,直接取jsonobject对象的值也是可以的;
  所以,更优雅的实现应该是从本质上解决问题。但是,从jdk的编译原理上,它是做不到泛型传递了。那怎么办?既然jdk会进行类型擦除,我们进行一次类型还原,是不是就能解决了?是的,思路如此。
  具体实现,则是将具体的泛型类,以class方式传入方法中,然后在方法进行类型还原即可!

具体我们来看下fastjson的实现:

  1. fastjson是如何解析普通泛型的?
  2. fastjson是如何解析多层嵌套泛型的?
  3. fastjson是如何还原泛型传递的?

我们一个个来源码:JsonObject.parseObject(); 首先对于无泛型对象,直接给出原始类就可以了。

    // com.alibaba.fastjson.JSON, 添加 DEFAULT_PARSER_FEATURE=989
    /**
     * <pre>
     * String jsonStr = "[{\"id\":1001,\"name\":\"Jobs\"}]";
     * List&lt;Model&gt; models = JSON.parseObject(jsonStr, new TypeReference&lt;List&lt;Model&gt;&gt;() {});
     * </pre>
     * @param text json string
     * @param type type refernce
     * @param features
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T parseObject(String text, TypeReference<T> type, Feature... features) {
        return (T) parseObject(text, type.type, ParserConfig.global, DEFAULT_PARSER_FEATURE, features);
    }
    
    public static <T> T parseObject(String input, Type clazz, ParserConfig config, int featureValues,
                                          Feature... features) {
        return parseObject(input, clazz, config, null, featureValues, features);
    }

    @SuppressWarnings("unchecked")
    public static <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor,
                                          int featureValues, Feature... features) {
        // null 直接返回 null
        if (input == null) {
            return null;
        }

        // feature 默认为空
        if (features != null) {
            for (Feature feature : features) {
                featureValues |= feature.mask;
            }
        }

        // 使用 DefaultJSONParser 解析, 将配置参数传入
        DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);

        // processor 不为空,则添加处理逻辑
        if (processor != null) {
            if (processor instanceof ExtraTypeProvider) {
                parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);
            }

            if (processor instanceof ExtraProcessor) {
                parser.getExtraProcessors().add((ExtraProcessor) processor);
            }

            if (processor instanceof FieldTypeResolver) {
                parser.setFieldTypeResolver((FieldTypeResolver) processor);
            }
        }

        // 直接调用 DefaultJSONParser.parseObject()
        T value = (T) parser.parseObject(clazz, null);

        // 处理 value resolveTask(), 
        parser.handleResovleTask(value);

        // 关闭输出流
        parser.close();

        return (T) value;
    }

  如上,就是json的的主流程,其实关键就在于 DefaultJSONParser 。如上操作就分几步:
    1. 分析 feature, 设置好, 关键是之前new 的 TypeReference 作为类信息传入配置;
    2. 将配置项全部载入 DefaultJSONParser 中, 以备后续使用;
    3. processor 配置添加;
    4. 调用 DefaultJSONParser.parseObject(), 做真正的解析动作;
    5. 异步 task 处理;
    6. 关闭输出流,并返回值;

  所以,我们主要来看 DefaultJSONParser 的处理逻辑;

    // com.alibaba.fastjson.parser.DefaultJSONParser 
    public DefaultJSONParser(final String input, final ParserConfig config, int features){
        // 初始化 JSONScanner -> JSONLexerBase, JSONScanner 将作为一个解析管道,顺序解析结果
        // 而 input 则作为一个原始值存在
        this(input, new JSONScanner(input, features), config);
    }

    public DefaultJSONParser(final Object input, final JSONLexer lexer, final ParserConfig config){
        this.lexer = lexer;
        this.input = input;
        this.config = config;
        this.symbolTable = config.symbolTable;

        int ch = lexer.getCurrent();
        // 根据第一个字符来判定要解析的类型, 以 "{" 开始的是json对象, "[" 开头的是 json 数组, 其他的直接取下一个字符串
        if (ch == ‘{‘) {
            lexer.next();
            ((JSONLexerBase) lexer).token = JSONToken.LBRACE;
        } else if (ch == ‘[‘) {
            lexer.next();
            ((JSONLexerBase) lexer).token = JSONToken.LBRACKET;
        } else {
            lexer.nextToken(); // prime the pump
        }
    }
    
    // 初始化好之后,进行关键的解析动作 parseObject()
    @SuppressWarnings("unchecked")
    public <T> T parseObject(Type type, Object fieldName) {
        // 把在构造函数中判断出的 token 类型, 取出判定
        int token = lexer.token();
        if (token == JSONToken.NULL) {
            lexer.nextToken();
            return null;
        }

        if (token == JSONToken.LITERAL_STRING) {
            if (type == byte[].class) {
                byte[] bytes = lexer.bytesValue();
                lexer.nextToken();
                return (T) bytes;
            }

            if (type == char[].class) {
                String strVal = lexer.stringVal();
                lexer.nextToken();
                return (T) strVal.toCharArray();
            }
        }

        // 关键: 获取反序列化器, 此处的type就是 TypeReference 推断出的 type
        // 实际类型为: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
        // 我们稍后看一下是如何获取反序列化器的
        ObjectDeserializer derializer = config.getDeserializer(type);

        try {
            if (derializer.getClass() == JavaBeanDeserializer.class) {
                // 对于复杂类型的解析, 单独转换后调入, feature 为 0
                return (T) ((JavaBeanDeserializer) derializer).deserialze(this, type, fieldName, 0);
            } else {
                return (T) derializer.deserialze(this, type, fieldName);
            }
        } catch (JSONException e) {
            throw e;
        } catch (Throwable e) {
            throw new JSONException(e.getMessage(), e);
        }
    }


    // com.alibaba.fastjson.parser.ParserConfig , 获取反序列化器
    public ObjectDeserializer getDeserializer(Type type) {
        ObjectDeserializer derializer = this.deserializers.get(type);
        if (derializer != null) {
            return derializer;
        }

        if (type instanceof Class<?>) {
            return getDeserializer((Class<?>) type, type);
        }

        // 通过 TypeReference 指定类型的type 为 ParameterizedTypeImpl, 所以会走此分支
        if (type instanceof ParameterizedType) {
            // 会取出最外层的 泛型 class, 以决定使用哪种 derializer
            Type rawType = ((ParameterizedType) type).getRawType();
            if (rawType instanceof Class<?>) {
                // 如果外层泛型为 class, 则进行实际泛型解析,否则递归操作先
                return getDeserializer((Class<?>) rawType, type);
            } else {
                return getDeserializer(rawType);
            }
        }

        if (type instanceof WildcardType) {
            WildcardType wildcardType = (WildcardType) type;
            Type[] upperBounds = wildcardType.getUpperBounds();
            if (upperBounds.length == 1) {
                Type upperBoundType = upperBounds[0];
                return getDeserializer(upperBoundType);
            }
        }

        return JavaObjectDeserializer.instance;
    }
    // 多重缓存并查
    public ObjectDeserializer getDeserializer(Class<?> clazz, Type type) {
        ObjectDeserializer derializer = deserializers.get(type);
        if (derializer != null) {
            return derializer;
        }

        if (type == null) {
            type = clazz;
        }

        // 排除 type 为空的情况,再次查询 derializers 缓存
        derializer = deserializers.get(type);
        if (derializer != null) {
            return derializer;
        }

        {
            // 使用 JSONType 注释的类处理
            JSONType annotation = TypeUtils.getAnnotation(clazz,JSONType.class);
            if (annotation != null) {
                Class<?> mappingTo = annotation.mappingTo();
                if (mappingTo != Void.class) {
                    return getDeserializer(mappingTo, mappingTo);
                }
            }
        }

        // 直接通过主类 clazz 获取反序列化器
        if (type instanceof WildcardType || type instanceof TypeVariable || type instanceof ParameterizedType) {
            derializer = deserializers.get(clazz);
        }

        if (derializer != null) {
            return derializer;
        }

        // 经过上面的筛选,仍然没有值,只能新计算了
        String className = clazz.getName();
        className = className.replace(‘$‘, ‘.‘);

        // awt 类库特殊处理
        if (className.startsWith("java.awt.") //
            && AwtCodec.support(clazz)) {
            if (!awtError) {
                String[] names = new String[] {
                        "java.awt.Point",
                        "java.awt.Font",
                        "java.awt.Rectangle",
                        "java.awt.Color"
                };

                try {
                    for (String name : names) {
                        if (name.equals(className)) {
                            deserializers.put(Class.forName(name), derializer = AwtCodec.instance);
                            return derializer;
                        }
                    }
                } catch (Throwable e) {
                    // skip
                    awtError = true;
                }

                derializer = AwtCodec.instance;
            }
        }

        // jdk8 的特殊类的解析
        if (!jdk8Error) {
            try {
                if (className.startsWith("java.time.")) {
                    String[] names = new String[] {
                            "java.time.LocalDateTime",
                            "java.time.LocalDate",
                            "java.time.LocalTime",
                            "java.time.ZonedDateTime",
                            "java.time.OffsetDateTime",
                            "java.time.OffsetTime",
                            "java.time.ZoneOffset",
                            "java.time.ZoneRegion",
                            "java.time.ZoneId",
                            "java.time.Period",
                            "java.time.Duration",
                            "java.time.Instant"
                    };

                    for (String name : names) {
                        if (name.equals(className)) {
                            deserializers.put(Class.forName(name), derializer = Jdk8DateCodec.instance);
                            return derializer;
                        }
                    }
                } else if (className.startsWith("java.util.Optional")) {
                    String[] names = new String[] {
                            "java.util.Optional",
                            "java.util.OptionalDouble",
                            "java.util.OptionalInt",
                            "java.util.OptionalLong"
                    };
                    for (String name : names) {
                        if (name.equals(className)) {
                            deserializers.put(Class.forName(name), derializer = OptionalCodec.instance);
                            return derializer;
                        }
                    }
                }
            } catch (Throwable e) {
                // skip
                jdk8Error = true;
            }
        }

        if (className.equals("java.nio.file.Path")) {
            deserializers.put(clazz, derializer = MiscCodec.instance);
        }

        if (clazz == Map.Entry.class) {
            deserializers.put(clazz, derializer = MiscCodec.instance);
        }

        final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        try {
            // 是否指定自定义的反序列化器?
            for (AutowiredObjectDeserializer autowired : ServiceLoader.load(AutowiredObjectDeserializer.class,
                                                                            classLoader)) {
                for (Type forType : autowired.getAutowiredFor()) {
                    deserializers.put(forType, autowired);
                }
            }
        } catch (Exception ex) {
            // skip
        }

        if (derializer == null) {
            derializer = deserializers.get(type);
        }

        if (derializer != null) {
            return derializer;
        }

        // 各种类型依次判定
        if (clazz.isEnum()) {
            Class<?> deserClass = null;
            JSONType jsonType = clazz.getAnnotation(JSONType.class);
            if (jsonType != null) {
                deserClass = jsonType.deserializer();
                try {
                    derializer = (ObjectDeserializer) deserClass.newInstance();
                    deserializers.put(clazz, derializer);
                    return derializer;
                } catch (Throwable error) {
                    // skip
                }
            }

            derializer = new EnumDeserializer(clazz);
        } else if (clazz.isArray()) {
            derializer = ObjectArrayCodec.instance;
        } else if (clazz == Set.class || clazz == HashSet.class || clazz == Collection.class || clazz == List.class
                   || clazz == ArrayList.class) {
            derializer = CollectionCodec.instance;
        } else if (Collection.class.isAssignableFrom(clazz)) {
            derializer = CollectionCodec.instance;
        } else if (Map.class.isAssignableFrom(clazz)) {
            derializer = MapDeserializer.instance;
        } else if (Throwable.class.isAssignableFrom(clazz)) {
            derializer = new ThrowableDeserializer(this, clazz);
        } else if (PropertyProcessable.class.isAssignableFrom(clazz)) {
            derializer = new PropertyProcessableDeserializer((Class<PropertyProcessable>) clazz);
        } else if (clazz == InetAddress.class) {
            derializer = MiscCodec.instance;
        } else {
            // 最后,其实会落到通用的 javaBeanDesializer 上, 这个创建可不简单,我们稍后看一下
            derializer = createJavaBeanDeserializer(clazz, type);
        }

        // 最后,将结果存入缓存,以便下一次查找
        putDeserializer(type, derializer);

        return derializer;
    }
    // 创建一个普通 javaBeanDesializer, type 中保存有所有的原始泛型类型,泛型的推断主要在这里看到
    public ObjectDeserializer createJavaBeanDeserializer(Class<?> clazz, Type type) {
        boolean asmEnable = this.asmEnable & !this.fieldBased;
        if (asmEnable) {
            JSONType jsonType = TypeUtils.getAnnotation(clazz,JSONType.class);

            if (jsonType != null) {
                Class<?> deserializerClass = jsonType.deserializer();
                if (deserializerClass != Void.class) {
                    try {
                        Object deseralizer = deserializerClass.newInstance();
                        if (deseralizer instanceof ObjectDeserializer) {
                            return (ObjectDeserializer) deseralizer;
                        }
                    } catch (Throwable e) {
                        // skip
                    }
                }
                
                asmEnable = jsonType.asm();
            }

            if (asmEnable) {
                // 优先查看 注解上的定义
                Class<?> superClass = JavaBeanInfo.getBuilderClass(clazz, jsonType);
                if (superClass == null) {
                    superClass = clazz;
                }

                for (;;) {
                    if (!Modifier.isPublic(superClass.getModifiers())) {
                        asmEnable = false;
                        break;
                    }

                    superClass = superClass.getSuperclass();
                    if (superClass == Object.class || superClass == null) {
                        break;
                    }
                }
            }
        }

        // 此处会取 T 的类型
        if (clazz.getTypeParameters().length != 0) {
            asmEnable = false;
        }

        if (asmEnable && asmFactory != null && asmFactory.classLoader.isExternalClass(clazz)) {
            asmEnable = false;
        }

        if (asmEnable) {
            asmEnable = ASMUtils.checkName(clazz.getSimpleName());
        }

        if (asmEnable) {
            if (clazz.isInterface()) {
                asmEnable = false;
            }
            JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, type, propertyNamingStrategy);

            if (asmEnable && beanInfo.fields.length > 200) {
                asmEnable = false;
            }

            Constructor<?> defaultConstructor = beanInfo.defaultConstructor;
            if (asmEnable && defaultConstructor == null && !clazz.isInterface()) {
                asmEnable = false;
            }

            for (FieldInfo fieldInfo : beanInfo.fields) {
                if (fieldInfo.getOnly) {
                    asmEnable = false;
                    break;
                }

                Class<?> fieldClass = fieldInfo.fieldClass;
                if (!Modifier.isPublic(fieldClass.getModifiers())) {
                    asmEnable = false;
                    break;
                }

                if (fieldClass.isMemberClass() && !Modifier.isStatic(fieldClass.getModifiers())) {
                    asmEnable = false;
                    break;
                }

                if (fieldInfo.getMember() != null //
                    && !ASMUtils.checkName(fieldInfo.getMember().getName())) {
                    asmEnable = false;
                    break;
                }

                JSONField annotation = fieldInfo.getAnnotation();
                if (annotation != null //
                    && ((!ASMUtils.checkName(annotation.name())) //
                        || annotation.format().length() != 0 //
                        || annotation.deserializeUsing() != Void.class //
                        || annotation.unwrapped())
                        || (fieldInfo.method != null && fieldInfo.method.getParameterTypes().length > 1)) {
                    asmEnable = false;
                    break;
                }

                if (fieldClass.isEnum()) { // EnumDeserializer
                    ObjectDeserializer fieldDeser = this.getDeserializer(fieldClass);
                    if (!(fieldDeser instanceof EnumDeserializer)) {
                        asmEnable = false;
                        break;
                    }
                }
            }
        }

        if (asmEnable) {
            if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) {
                asmEnable = false;
            }
        }

        // 总之,前面的判断都只是为了检查是否可以使用 asm 进行反序列化
        if (!asmEnable) {
            // 不能则返回 JavaBeanDeserializer
            return new JavaBeanDeserializer(this, clazz, type);
        }

        JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, type, propertyNamingStrategy);
        try {
            return asmFactory.createJavaBeanDeserializer(this, beanInfo);
            // } catch (VerifyError e) {
            // e.printStackTrace();
            // return new JavaBeanDeserializer(this, clazz, type);
        } catch (NoSuchMethodException ex) {
            return new JavaBeanDeserializer(this, clazz, type);
        } catch (JSONException asmError) {
            return new JavaBeanDeserializer(this, beanInfo);
        } catch (Exception e) {
            throw new JSONException("create asm deserializer error, " + clazz.getName(), e);
        }
    }

 

序列化器构造详情

技术图片
    // com.alibaba.fastjson.parser.deserializerBeanDeserializer
    public JavaBeanDeserializer(ParserConfig config, Class<?> clazz, Type type){
        // 此处 JavaBeanInfo 的创建也是大工程啊, 
        this(config //
                , JavaBeanInfo.build(clazz, type, config.propertyNamingStrategy, config.fieldBased, config.compatibleWithJavaBean)
        );
    }
    
    public JavaBeanDeserializer(ParserConfig config, JavaBeanInfo beanInfo){
        this.clazz = beanInfo.clazz;
        this.beanInfo = beanInfo;

        Map<String, FieldDeserializer> alterNameFieldDeserializers = null;
        sortedFieldDeserializers = new FieldDeserializer[beanInfo.sortedFields.length];
        for (int i = 0, size = beanInfo.sortedFields.length; i < size; ++i) {
            FieldInfo fieldInfo = beanInfo.sortedFields[i];
            FieldDeserializer fieldDeserializer = config.createFieldDeserializer(config, beanInfo, fieldInfo);

            sortedFieldDeserializers[i] = fieldDeserializer;

            for (String name : fieldInfo.alternateNames) {
                if (alterNameFieldDeserializers == null) {
                    alterNameFieldDeserializers = new HashMap<String, FieldDeserializer>();
                }
                alterNameFieldDeserializers.put(name, fieldDeserializer);
            }
        }
        this.alterNameFieldDeserializers = alterNameFieldDeserializers;

        fieldDeserializers = new FieldDeserializer[beanInfo.fields.length];
        for (int i = 0, size = beanInfo.fields.length; i < size; ++i) {
            FieldInfo fieldInfo = beanInfo.fields[i];
            // 此处会使用已排好序的 sortedFieldDeserializers 进行查找
            FieldDeserializer fieldDeserializer = getFieldDeserializer(fieldInfo.name);
            fieldDeserializers[i] = fieldDeserializer;
        }
    }

    // com.alibaba.fastjson.utilBeanInfo, 几百行的 JavaBeanInfo 的创建过程
    public static JavaBeanInfo build(Class<?> clazz //
            , Type type //
            , PropertyNamingStrategy propertyNamingStrategy //
            , boolean fieldBased //
            , boolean compatibleWithJavaBean
    ) {
        JSONType jsonType = TypeUtils.getAnnotation(clazz,JSONType.class);
        if (jsonType != null) {
            PropertyNamingStrategy jsonTypeNaming = jsonType.naming();
            if (jsonTypeNaming != null && jsonTypeNaming != PropertyNamingStrategy.CamelCase) {
                propertyNamingStrategy = jsonTypeNaming;
            }
        }

        Class<?> builderClass = getBuilderClass(clazz, jsonType);

        // 取出字段和方法
        Field[] declaredFields = clazz.getDeclaredFields();
        Method[] methods = clazz.getMethods();

        boolean kotlin = TypeUtils.isKotlin(clazz);
        Constructor[] constructors = clazz.getDeclaredConstructors();

        Constructor<?> defaultConstructor = null;
        if ((!kotlin) || constructors.length == 1) {
            if (builderClass == null) {
                // 默认无参构造器
                defaultConstructor = getDefaultConstructor(clazz, constructors);
            } else {
                defaultConstructor = getDefaultConstructor(builderClass, builderClass.getDeclaredConstructors());
            }
        }

        Constructor<?> creatorConstructor = null;
        Method buildMethod = null;
        Method factoryMethod = null;

        List<FieldInfo> fieldList = new ArrayList<FieldInfo>();

        if (fieldBased) {
            for (Class<?> currentClass = clazz; currentClass != null; currentClass = currentClass.getSuperclass()) {
                Field[] fields = currentClass.getDeclaredFields();

                computeFields(clazz, type, propertyNamingStrategy, fieldList, fields);
            }
            return new JavaBeanInfo(clazz, builderClass, defaultConstructor, null, factoryMethod, buildMethod, jsonType, fieldList);
        }

        boolean isInterfaceOrAbstract = clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers());
        if ((defaultConstructor == null && builderClass == null) || isInterfaceOrAbstract) {
            creatorConstructor = getCreatorConstructor(constructors);

            if (creatorConstructor != null && !isInterfaceOrAbstract) { // 基于标记 JSONCreator 注解的构造方法
                TypeUtils.setAccessible(creatorConstructor);

                Class<?>[] types = creatorConstructor.getParameterTypes();

                String[] lookupParameterNames = null;
                if (types.length > 0) {
                    Annotation[][] paramAnnotationArrays = creatorConstructor.getParameterAnnotations();
                    for (int i = 0; i < types.length; ++i) {
                        Annotation[] paramAnnotations = paramAnnotationArrays[i];
                        JSONField fieldAnnotation = null;
                        for (Annotation paramAnnotation : paramAnnotations) {
                            if (paramAnnotation instanceof JSONField) {
                                fieldAnnotation = (JSONField) paramAnnotation;
                                break;
                            }
                        }

                        Class<?> fieldClass = types[i];
                        Type fieldType = creatorConstructor.getGenericParameterTypes()[i];

                        String fieldName = null;
                        Field field = null;
                        int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0;
                        if (fieldAnnotation != null) {
                            field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields);
                            ordinal = fieldAnnotation.ordinal();
                            serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
                            parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
                            fieldName = fieldAnnotation.name();
                        }

                        if (fieldName == null || fieldName.length() == 0) {
                            if (lookupParameterNames == null) {
                                lookupParameterNames = ASMUtils.lookupParameterNames(creatorConstructor);
                            }
                            fieldName = lookupParameterNames[i];
                        }

                        FieldInfo fieldInfo = new FieldInfo(fieldName, clazz, fieldClass, fieldType, field,
                                ordinal, serialzeFeatures, parserFeatures);
                        add(fieldList, fieldInfo);
                    }
                }

                //return new JavaBeanInfo(clazz, builderClass, null, creatorConstructor, null, null, jsonType, fieldList);
            } else if ((factoryMethod = getFactoryMethod(clazz, methods)) != null) {
                TypeUtils.setAccessible(factoryMethod);

                Class<?>[] types = factoryMethod.getParameterTypes();
                if (types.length > 0) {
                    Annotation[][] paramAnnotationArrays = factoryMethod.getParameterAnnotations();
                    for (int i = 0; i < types.length; ++i) {
                        Annotation[] paramAnnotations = paramAnnotationArrays[i];
                        JSONField fieldAnnotation = null;
                        for (Annotation paramAnnotation : paramAnnotations) {
                            if (paramAnnotation instanceof JSONField) {
                                fieldAnnotation = (JSONField) paramAnnotation;
                                break;
                            }
                        }
                        if (fieldAnnotation == null) {
                            throw new JSONException("illegal json creator");
                        }

                        Class<?> fieldClass = types[i];
                        Type fieldType = factoryMethod.getGenericParameterTypes()[i];
                        Field field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields);
                        final int ordinal = fieldAnnotation.ordinal();
                        final int serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
                        final int parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
                        FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name(), clazz, fieldClass, fieldType, field,
                                ordinal, serialzeFeatures, parserFeatures);
                        add(fieldList, fieldInfo);
                    }

                    return new JavaBeanInfo(clazz, builderClass, null, null, factoryMethod, null, jsonType, fieldList);
                }
            } else if (!isInterfaceOrAbstract) {
                String className = clazz.getName();

                String[] paramNames = null;
                if (kotlin && constructors.length > 0) {
                    paramNames = TypeUtils.getKoltinConstructorParameters(clazz);
                    creatorConstructor = TypeUtils.getKoltinConstructor(constructors, paramNames);
                    TypeUtils.setAccessible(creatorConstructor);
                } else {

                    for (Constructor constructor : constructors) {
                        Class<?>[] parameterTypes = constructor.getParameterTypes();

                        if (className.equals("org.springframework.security.web.authentication.WebAuthenticationDetails")) {
                            if (parameterTypes.length == 2 && parameterTypes[0] == String.class && parameterTypes[1] == String.class) {
                                creatorConstructor = constructor;
                                creatorConstructor.setAccessible(true);
                                paramNames = ASMUtils.lookupParameterNames(constructor);
                                break;
                            }
                        }

                        if (className.equals("org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken")) {
                            if (parameterTypes.length == 3
                                    && parameterTypes[0] == Object.class
                                    && parameterTypes[1] == Object.class
                                    && parameterTypes[2] == Collection.class) {
                                creatorConstructor = constructor;
                                creatorConstructor.setAccessible(true);
                                paramNames = new String[] {"principal", "credentials", "authorities"};
                                break;
                            }
                        }

                        if (className.equals("org.springframework.security.core.authority.SimpleGrantedAuthority")) {
                            if (parameterTypes.length == 1
                                    && parameterTypes[0] == String.class) {
                                creatorConstructor = constructor;
                                paramNames = new String[] {"authority"};
                                break;
                            }
                        }

                        //


                        boolean is_public = (constructor.getModifiers() & Modifier.PUBLIC) != 0;
                        if (!is_public) {
                            continue;
                        }
                        String[] lookupParameterNames = ASMUtils.lookupParameterNames(constructor);
                        if (lookupParameterNames == null || lookupParameterNames.length == 0) {
                            continue;
                        }

                        if (creatorConstructor != null
                                && paramNames != null && lookupParameterNames.length <= paramNames.length) {
                            continue;
                        }

                        paramNames = lookupParameterNames;
                        creatorConstructor = constructor;
                    }
                }

                Class<?>[] types = null;
                if (paramNames != null) {
                    types = creatorConstructor.getParameterTypes();
                }

                if (paramNames != null
                        && types.length == paramNames.length) {
                    Annotation[][] paramAnnotationArrays = creatorConstructor.getParameterAnnotations();
                    for (int i = 0; i < types.length; ++i) {
                        Annotation[] paramAnnotations = paramAnnotationArrays[i];
                        String paramName = paramNames[i];

                        JSONField fieldAnnotation = null;
                        for (Annotation paramAnnotation : paramAnnotations) {
                            if (paramAnnotation instanceof JSONField) {
                                fieldAnnotation = (JSONField) paramAnnotation;
                                break;
                            }
                        }

                        Class<?> fieldClass = types[i];
                        Type fieldType = creatorConstructor.getGenericParameterTypes()[i];
                        Field field = TypeUtils.getField(clazz, paramName, declaredFields);
                        if (field != null) {
                            if (fieldAnnotation == null) {
                                fieldAnnotation = field.getAnnotation(JSONField.class);
                            }
                        }
                        final int ordinal, serialzeFeatures, parserFeatures;
                        if (fieldAnnotation == null) {
                            ordinal = 0;
                            serialzeFeatures = 0;

                            if ("org.springframework.security.core.userdetails.User".equals(className)
                                    && "password".equals(paramName)) {
                                parserFeatures = Feature.InitStringFieldAsEmpty.mask;
                            } else {
                                parserFeatures = 0;
                            }
                        } else {
                            String nameAnnotated = fieldAnnotation.name();
                            if (nameAnnotated.length() != 0) {
                                paramName = nameAnnotated;
                            }
                            ordinal = fieldAnnotation.ordinal();
                            serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
                            parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
                        }
                        FieldInfo fieldInfo = new FieldInfo(paramName, clazz, fieldClass, fieldType, field,
                                ordinal, serialzeFeatures, parserFeatures);
                        add(fieldList, fieldInfo);
                    }

                    if ((!kotlin)
                            && !clazz.getName().equals("javax.servlet.http.Cookie")) {
                        return new JavaBeanInfo(clazz, builderClass, null, creatorConstructor, null, null, jsonType, fieldList);
                    }
                } else {
                    throw new JSONException("default constructor not found. " + clazz);
                }
            }
        }

        if (defaultConstructor != null) {
            TypeUtils.setAccessible(defaultConstructor);
        }

        if (builderClass != null) {
            String withPrefix = null;

            JSONPOJOBuilder builderAnno = builderClass.getAnnotation(JSONPOJOBuilder.class);
            if (builderAnno != null) {
                withPrefix = builderAnno.withPrefix();
            }

            if (withPrefix == null || withPrefix.length() == 0) {
                withPrefix = "with";
            }

            for (Method method : builderClass.getMethods()) {
                if (Modifier.isStatic(method.getModifiers())) {
                    continue;
                }

                if (!(method.getReturnType().equals(builderClass))) {
                    continue;
                }

                int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0;

                JSONField annotation = method.getAnnotation(JSONField.class);

                if (annotation == null) {
                    annotation = TypeUtils.getSuperMethodAnnotation(clazz, method);
                }

                if (annotation != null) {
                    if (!annotation.deserialize()) {
                        continue;
                    }

                    ordinal = annotation.ordinal();
                    serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures());
                    parserFeatures = Feature.of(annotation.parseFeatures());

                    if (annotation.name().length() != 0) {
                        String propertyName = annotation.name();
                        add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures, parserFeatures,
                                annotation, null, null));
                        continue;
                    }
                }

                String methodName = method.getName();
                StringBuilder properNameBuilder;
                if (methodName.startsWith("set") && methodName.length() > 3) {
                    properNameBuilder = new StringBuilder(methodName.substring(3));
                } else {
                    if (!methodName.startsWith(withPrefix)) {
                        continue;
                    }

                    if (methodName.length() <= withPrefix.length()) {
                        continue;
                    }

                    properNameBuilder = new StringBuilder(methodName.substring(withPrefix.length()));
                }

                char c0 = properNameBuilder.charAt(0);
                if (!Character.isUpperCase(c0)) {
                    continue;
                }

                properNameBuilder.setCharAt(0, Character.toLowerCase(c0));

                String propertyName = properNameBuilder.toString();

                add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures, parserFeatures,
                        annotation, null, null));
            }

            if (builderClass != null) {
                JSONPOJOBuilder builderAnnotation = builderClass.getAnnotation(JSONPOJOBuilder.class);

                String buildMethodName = null;
                if (builderAnnotation != null) {
                    buildMethodName = builderAnnotation.buildMethod();
                }

                if (buildMethodName == null || buildMethodName.length() == 0) {
                    buildMethodName = "build";
                }

                try {
                    buildMethod = builderClass.getMethod(buildMethodName);
                } catch (NoSuchMethodException e) {
                    // skip
                } catch (SecurityException e) {
                    // skip
                }

                if (buildMethod == null) {
                    try {
                        buildMethod = builderClass.getMethod("create");
                    } catch (NoSuchMethodException e) {
                        // skip
                    } catch (SecurityException e) {
                        // skip
                    }
                }

                if (buildMethod == null) {
                    throw new JSONException("buildMethod not found.");
                }

                TypeUtils.setAccessible(buildMethod);
            }
        }

        for (Method method : methods) { //
            int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0;
            String methodName = method.getName();

            if (Modifier.isStatic(method.getModifiers())) {
                continue;
            }

            // support builder set
            Class<?> returnType = method.getReturnType();
            if (!(returnType.equals(Void.TYPE) || returnType.equals(method.getDeclaringClass()))) {
                continue;
            }

            if (method.getDeclaringClass() == Object.class) {
                continue;
            }

            Class<?>[] types = method.getParameterTypes();

            if (types.length == 0 || types.length > 2) {
                continue;
            }

            JSONField annotation = method.getAnnotation(JSONField.class);
            if (annotation != null
                    && types.length == 2
                    && types[0] == String.class
                    && types[1] == Object.class) {
                add(fieldList, new FieldInfo("", method, null, clazz, type, ordinal,
                        serialzeFeatures, parserFeatures, annotation, null, null));
                continue;
            }

            if (types.length != 1) {
                continue;
            }

            if (annotation == null) {
                annotation = TypeUtils.getSuperMethodAnnotation(clazz, method);
            }

            if (annotation == null && methodName.length() < 4) {
                continue;
            }

            if (annotation != null) {
                if (!annotation.deserialize()) {
                    continue;
                }

                ordinal = annotation.ordinal();
                serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures());
                parserFeatures = Feature.of(annotation.parseFeatures());

                if (annotation.name().length() != 0) {
                    String propertyName = annotation.name();
                    add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, ordinal, serialzeFeatures, parserFeatures,
                            annotation, null, null));
                    continue;
                }
            }

            if (annotation == null && !methodName.startsWith("set")) { // TODO "set"的判断放在 JSONField 注解后面,意思是允许非 setter 方法标记 JSONField 注解?
                continue;
            }

            char c3 = methodName.charAt(3);

            String propertyName;
            if (Character.isUpperCase(c3) //
                    || c3 > 512 // for unicode method name
                    ) {
                if (TypeUtils.compatibleWithJavaBean) {
                    propertyName = TypeUtils.decapitalize(methodName.substring(3));
                } else {
                    propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
                }
            } else if (c3 == ‘_‘) {
                propertyName = methodName.substring(4);
            } else if (c3 == ‘f‘) {
                propertyName = methodName.substring(3);
            } else if (methodName.length() >= 5 && Character.isUpperCase(methodName.charAt(4))) {
                propertyName = TypeUtils.decapitalize(methodName.substring(3));
            } else {
                continue;
            }

            Field field = TypeUtils.getField(clazz, propertyName, declaredFields);
            if (field == null && types[0] == boolean.class) {
                String isFieldName = "is" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
                field = TypeUtils.getField(clazz, isFieldName, declaredFields);
            }

            JSONField fieldAnnotation = null;
            if (field != null) {
                fieldAnnotation = field.getAnnotation(JSONField.class);

                if (fieldAnnotation != null) {
                    if (!fieldAnnotation.deserialize()) {
                        continue;
                    }

                    ordinal = fieldAnnotation.ordinal();
                    serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
                    parserFeatures = Feature.of(fieldAnnotation.parseFeatures());

                    if (fieldAnnotation.name().length() != 0) {
                        propertyName = fieldAnnotation.name();
                        add(fieldList, new FieldInfo(propertyName, method, field, clazz, type, ordinal,
                                serialzeFeatures, parserFeatures, annotation, fieldAnnotation, null));
                        continue;
                    }
                }

            }

            if (propertyNamingStrategy != null) {
                propertyName = propertyNamingStrategy.translate(propertyName);
            }
            // 添加解析出的字段到 fieldList 中
            add(fieldList, new FieldInfo(propertyName, method, field, clazz, type, ordinal, serialzeFeatures, parserFeatures,
                    annotation, fieldAnnotation, null));
        }

        // 因为在上面加入了一些字段,所以现在重新取字段
        Field[] fields = clazz.getFields();
        computeFields(clazz, type, propertyNamingStrategy, fieldList, fields);

        for (Method method : clazz.getMethods()) { // getter methods
            String methodName = method.getName();
            if (methodName.length() < 4) {
                continue;
            }

            if (Modifier.isStatic(method.getModifiers())) {
                continue;
            }

            if (builderClass == null && methodName.startsWith("get") && Character.isUpperCase(methodName.charAt(3))) {
                if (method.getParameterTypes().length != 0) {
                    continue;
                }

                if (Collection.class.isAssignableFrom(method.getReturnType()) //
                        || Map.class.isAssignableFrom(method.getReturnType()) //
                        || AtomicBoolean.class == method.getReturnType() //
                        || AtomicInteger.class == method.getReturnType() //
                        || AtomicLong.class == method.getReturnType() //
                        ) {
                    String propertyName;

                    JSONField annotation = method.getAnnotation(JSONField.class);
                    if (annotation != null && annotation.deserialize()) {
                        continue;
                    }

                    if (annotation != null && annotation.name().length() > 0) {
                        propertyName = annotation.name();
                    } else {
                        propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);

                        Field field = TypeUtils.getField(clazz, propertyName, declaredFields);
                        if (field != null) {
                            JSONField fieldAnnotation = field.getAnnotation(JSONField.class);
                            if (fieldAnnotation != null && !fieldAnnotation.deserialize()) {
                                continue;
                            }
                        }
                    }

                    if (propertyNamingStrategy != null) {
                        propertyName = propertyNamingStrategy.translate(propertyName);
                    }

                    FieldInfo fieldInfo = getField(fieldList, propertyName);
                    if (fieldInfo != null) {
                        continue;
                    }

                    add(fieldList, new FieldInfo(propertyName, method, null, clazz, type, 0, 0, 0, annotation, null, null));
                }
            }
        }
        // 最后返回 JavaBeanInfo
        return new JavaBeanInfo(clazz, builderClass, defaultConstructor, creatorConstructor, factoryMethod, buildMethod, jsonType, fieldList);
    }
View Code

 

序列化构造器详情2:

技术图片
    // com.alibaba.fastjson.util.FieldInfo , 构建字段信息
    public FieldInfo(String name, // 
                     Method method, // 
                     Field field, // 
                     Class<?> clazz, // 
                     Type type, // 
                     int ordinal, // 
                     int serialzeFeatures, // 
                     int parserFeatures, //
                     JSONField fieldAnnotation, // 
                     JSONField methodAnnotation, //
                     String label){
        if (field != null) {
            String fieldName = field.getName();
            if (fieldName.equals(name)) {
                name = fieldName;
            }
        }

        if (ordinal < 0) {
            ordinal = 0;
        }
        
        this.name = name;
        this.method = method;
        this.field = field;
        this.ordinal = ordinal;
        this.serialzeFeatures = serialzeFeatures;
        this.parserFeatures = parserFeatures;
        this.fieldAnnotation = fieldAnnotation;
        this.methodAnnotation = methodAnnotation;
        
        if (field != null) {
            int modifiers = field.getModifiers();
            fieldAccess = ((modifiers & Modifier.PUBLIC) != 0 || method == null);
            fieldTransient = Modifier.isTransient(modifiers)
                    || TypeUtils.isTransient(method);
        } else {
            fieldAccess = false;
            fieldTransient = false;
        }
        
        if (label != null && label.length() > 0) { 
            this.label = label;
        } else {
            this.label = "";
        }
        
        String format = null;
        JSONField annotation = getAnnotation();

        boolean jsonDirect = false;
        if (annotation != null) {
            format = annotation.format();

            if (format.trim().length() == 0) {
                format = null;
            }
            jsonDirect = annotation.jsonDirect();
            unwrapped = annotation.unwrapped();
            alternateNames = annotation.alternateNames();
        } else {
            jsonDirect = false;
            unwrapped = false;
            alternateNames = new String[0];
        }
        this.format = format;
        
        name_chars = genFieldNameChars();

        if (method != null) {
            TypeUtils.setAccessible(method);
        }

        if (field != null) {
            TypeUtils.setAccessible(field);
        }

        boolean getOnly = false;
        Type fieldType;
        Class<?> fieldClass;
        if (method != null) {
            Class<?>[] types;
            if ((types = method.getParameterTypes()).length == 1) {
                // 泛型在此变为 java.lang.Object
                // 所以,泛型的推断关键,就交给了 type 字段的设值了
                fieldClass = types[0];
                // 泛型可推断出值, 如题中  Map<String, T>, 此处将得出 T 的 TypeVariableImpl , 但是 fieldClass = java.lang.Object
                fieldType = method.getGenericParameterTypes()[0];
            } else if (types.length == 2 && types[0] == String.class && types[1] == Object.class) {
                fieldType = fieldClass = types[0];
            } else {
                fieldClass = method.getReturnType();
                fieldType = method.getGenericReturnType();
                getOnly = true;
            }
            this.declaringClass = method.getDeclaringClass();
        } else {
            fieldClass = field.getType();
            fieldType = field.getGenericType();
            this.declaringClass = field.getDeclaringClass();
            getOnly = Modifier.isFinal(field.getModifiers());
        }
        this.getOnly = getOnly;
        this.jsonDirect = jsonDirect && fieldClass == String.class;

        if (clazz != null && fieldClass == Object.class && fieldType instanceof TypeVariable) {
            TypeVariable<?> tv = (TypeVariable<?>) fieldType;
            // 再次通过原始指定的泛型进行一次推断,得到泛型的真正类,从而达到还原泛型的目的
            // 泛型的继承关系推断
            Type genericFieldType = getInheritGenericType(clazz, type, tv);
            if (genericFieldType != null) {
                this.fieldClass = TypeUtils.getClass(genericFieldType);
                this.fieldType = genericFieldType;
                
                isEnum = fieldClass.isEnum();
                return;
            }
        }

        Type genericFieldType = fieldType;
        
        if (!(fieldType instanceof Class)) {
            genericFieldType = getFieldType(clazz, type != null ? type : clazz, fieldType);
    
            if (genericFieldType != fieldType) {
                if (genericFieldType instanceof ParameterizedType) {
                    fieldClass = TypeUtils.getClass(genericFieldType);
                } else if (genericFieldType instanceof Class) {
                    fieldClass = TypeUtils.getClass(genericFieldType);
                }
            }
        }

        this.fieldType = genericFieldType;
        this.fieldClass = fieldClass;
        
        isEnum = fieldClass.isEnum();
    }
    
    private static Type getInheritGenericType(Class<?> clazz, Type type, TypeVariable<?> tv) {
        GenericDeclaration gd = tv.getGenericDeclaration();

        Class<?> class_gd = null;
        if (gd instanceof Class) {
            class_gd = (Class<?>) tv.getGenericDeclaration();
        }

        Type[] arguments = null;
        if (class_gd == clazz) {
            // 泛型的还原都是通过 ParameterizedType 来实现的 
            // 此处会一层层还原,如题的操作第一层还原将得到 java.util.Map<String, T>
            // 所以,泛型的推断关键,就交给了 type 字段的设值了
            if (type instanceof ParameterizedType) {
                ParameterizedType ptype = (ParameterizedType) type;
                // 设置的泛型会在此处进行体现 
                arguments = ptype.getActualTypeArguments();
            }
        } else {
            for (Class<?> c = clazz; c != null && c != Object.class && c != class_gd; c = c.getSuperclass()) {
                Type superType = c.getGenericSuperclass();

                if (superType instanceof ParameterizedType) {
                    ParameterizedType p_superType = (ParameterizedType) superType;
                    Type[] p_superType_args = p_superType.getActualTypeArguments();
                    getArgument(p_superType_args, c.getTypeParameters(), arguments);
                    arguments = p_superType_args;
                }
            }
        }

        if (arguments == null || class_gd == null) {
            return null;
        }

        Type actualType = null;
        // 此处将会获取到泛型 T, 与 将 tv 与 typeVariables 进行比较,如果找到设置值则,得出泛型的原型,以待后用
        TypeVariable<?>[] typeVariables = class_gd.getTypeParameters();
        for (int j = 0; j < typeVariables.length; ++j) {
            // 最终的泛型结果,在查找中得到
            if (tv.equals(typeVariables[j])) {
                actualType = arguments[j];
                break;
            }
        }
        // Map<String, T>
        return actualType;
    }

    private static Type getInheritGenericType(Class<?> clazz, Type type, TypeVariable<?> tv) {
        GenericDeclaration gd = tv.getGenericDeclaration();

        Class<?> class_gd = null;
        if (gd instanceof Class) {
            class_gd = (Class<?>) tv.getGenericDeclaration();
        }

        Type[] arguments = null;
        if (class_gd == clazz) {
            if (type instanceof ParameterizedType) {
                ParameterizedType ptype = (ParameterizedType) type;
                arguments = ptype.getActualTypeArguments();
            }
        } else {
            for (Class<?> c = clazz; c != null && c != Object.class && c != class_gd; c = c.getSuperclass()) {
                Type superType = c.getGenericSuperclass();

                if (superType instanceof ParameterizedType) {
                    ParameterizedType p_superType = (ParameterizedType) superType;
                    Type[] p_superType_args = p_superType.getActualTypeArguments();
                    getArgument(p_superType_args, c.getTypeParameters(), arguments);
                    arguments = p_superType_args;
                }
            }
        }

        if (arguments == null || class_gd == null) {
            return null;
        }

        Type actualType = null;
        TypeVariable<?>[] typeVariables = class_gd.getTypeParameters();
        for (int j = 0; j < typeVariables.length; ++j) {
            if (tv.equals(typeVariables[j])) {
                actualType = arguments[j];
                break;
            }
        }

        return actualType;
    }
    
    // 参数配置好后,new JavaBeanInfo()
    public JavaBeanInfo(Class<?> clazz, //
                        Class<?> builderClass, //
                        Constructor<?> defaultConstructor, //
                        Constructor<?> creatorConstructor, //
                        Method factoryMethod, //
                        Method buildMethod, //
                        JSONType jsonType, //
                        List<FieldInfo> fieldList) {
        this.clazz = clazz;
        this.builderClass = builderClass;
        this.defaultConstructor = defaultConstructor;
        this.creatorConstructor = creatorConstructor;
        this.factoryMethod = factoryMethod;
        this.parserFeatures = TypeUtils.getParserFeatures(clazz);
        this.buildMethod = buildMethod;

        this.jsonType = jsonType;
        if (jsonType != null) {
            String typeName = jsonType.typeName();
            String typeKey = jsonType.typeKey();
            this.typeKey = typeKey.length() > 0 ? typeKey : null;

            if (typeName.length() != 0) {
                this.typeName = typeName;
            } else {
                this.typeName = clazz.getName();
            }
            String[] orders = jsonType.orders();
            this.orders = orders.length == 0 ? null : orders;
        } else {
            this.typeName = clazz.getName();
            this.typeKey = null;
            this.orders = null;
        }

        // 字段信息
        fields = new FieldInfo[fieldList.size()];
        fieldList.toArray(fields);

        FieldInfo[] sortedFields = new FieldInfo[fields.length];
        if (orders != null) {
            LinkedHashMap<String, FieldInfo> map = new LinkedHashMap<String, FieldInfo>(fieldList.size());
            for (FieldInfo field : fields) {
                map.put(field.name, field);
            }
            int i = 0;
            for (String item : orders) {
                FieldInfo field = map.get(item);
                if (field != null) {
                    sortedFields[i++] = field;
                    map.remove(item);
                }
            }
            for (FieldInfo field : map.values()) {
                sortedFields[i++] = field;
            }
        } else {
            System.arraycopy(fields, 0, sortedFields, 0, fields.length);
            Arrays.sort(sortedFields);
        }

        if (Arrays.equals(fields, sortedFields)) {
            sortedFields = fields;
        }
        this.sortedFields = sortedFields;

        if (defaultConstructor != null) {
            defaultConstructorParameterSize = defaultConstructor.getParameterTypes().length;
        } else if (factoryMethod != null) {
            defaultConstructorParameterSize = factoryMethod.getParameterTypes().length;
        } else {
            defaultConstructorParameterSize = 0;
        }

        if (creatorConstructor != null) {
            this.creatorConstructorParameterTypes = creatorConstructor.getParameterTypes();


            kotlin = TypeUtils.isKotlin(clazz);
            if (kotlin) {
                this.creatorConstructorParameters = TypeUtils.getKoltinConstructorParameters(clazz);
                try {
                    this.kotlinDefaultConstructor = clazz.getConstructor();
                } catch (Throwable ex) {
                    // skip
                }

                Annotation[][] paramAnnotationArrays = creatorConstructor.getParameterAnnotations();
                for (int i = 0; i < creatorConstructorParameters.length && i < paramAnnotationArrays.length; ++i) {
                    Annotation[] paramAnnotations = paramAnnotationArrays[i];
                    JSONField fieldAnnotation = null;
                    for (Annotation paramAnnotation : paramAnnotations) {
                        if (paramAnnotation instanceof JSONField) {
                            fieldAnnotation = (JSONField) paramAnnotation;
                            break;
                        }
                    }
                    if (fieldAnnotation != null) {
                        String fieldAnnotationName = fieldAnnotation.name();
                        if (fieldAnnotationName.length() > 0) {
                            creatorConstructorParameters[i] = fieldAnnotationName;
                        }
                    }
                }
            } else {
                boolean match;
                if (creatorConstructorParameterTypes.length != fields.length) {
                    match = false;
                } else {
                    match = true;
                    for (int i = 0; i < creatorConstructorParameterTypes.length; i++) {
                        if (creatorConstructorParameterTypes[i] != fields[i].fieldClass) {
                            match = false;
                            break;
                        }
                    }
                }

                if (!match) {
                    this.creatorConstructorParameters = ASMUtils.lookupParameterNames(creatorConstructor);
                }
            }
        }
    }
    
    // com.alibaba.fastjson.parser.deserializerBeanDeserializer
    public JavaBeanDeserializer(ParserConfig config, Class<?> clazz, Type type){
        this(config //
                , JavaBeanInfo.build(clazz, type, config.propertyNamingStrategy, config.fieldBased, config.compatibleWithJavaBean)
        );
    }
    
    public JavaBeanDeserializer(ParserConfig config, JavaBeanInfo beanInfo){
        this.clazz = beanInfo.clazz;
        this.beanInfo = beanInfo;

        Map<String, FieldDeserializer> alterNameFieldDeserializers = null;
        sortedFieldDeserializers = new FieldDeserializer[beanInfo.sortedFields.length];
        for (int i = 0, size = beanInfo.sortedFields.length; i < size; ++i) {
            // 将前端解析出的字段配置取出, 为每个字段创建一个解析器
            FieldInfo fieldInfo = beanInfo.sortedFields[i];
            FieldDeserializer fieldDeserializer = config.createFieldDeserializer(config, beanInfo, fieldInfo);
            // 将对应的反序列化器放入到对应的位置
            sortedFieldDeserializers[i] = fieldDeserializer;

            for (String name : fieldInfo.alternateNames) {
                if (alterNameFieldDeserializers == null) {
                    alterNameFieldDeserializers = new HashMap<String, FieldDeserializer>();
                }
                alterNameFieldDeserializers.put(name, fieldDeserializer);
            }
        }
        this.alterNameFieldDeserializers = alterNameFieldDeserializers;

        fieldDeserializers = new FieldDeserializer[beanInfo.fields.length];
        for (int i = 0, size = beanInfo.fields.length; i < size; ++i) {
            FieldInfo fieldInfo = beanInfo.fields[i];
            // 根据 key 查找序列化器, 使用二分查找法
            FieldDeserializer fieldDeserializer = getFieldDeserializer(fieldInfo.name);
            fieldDeserializers[i] = fieldDeserializer;
        }
    }

    // com.alibaba.fastjson.parser.ParserConfig
    public FieldDeserializer createFieldDeserializer(ParserConfig mapping, //
                                                     JavaBeanInfo beanInfo, //
                                                     FieldInfo fieldInfo) {
        Class<?> clazz = beanInfo.clazz;
        Class<?> fieldClass = fieldInfo.fieldClass;

        Class<?> deserializeUsing = null;
        JSONField annotation = fieldInfo.getAnnotation();
        if (annotation != null) {
            deserializeUsing = annotation.deserializeUsing();
            if (deserializeUsing == Void.class) {
                deserializeUsing = null;
            }
        }

        if (deserializeUsing == null && (fieldClass == List.class || fieldClass == ArrayList.class)) {
            return new ArrayListTypeFieldDeserializer(mapping, clazz, fieldInfo);
        }

        return new DefaultFieldDeserializer(mapping, clazz, fieldInfo);
    }

    public FieldDeserializer getFieldDeserializer(String key) {
        return getFieldDeserializer(key, null);
    }

    public FieldDeserializer getFieldDeserializer(String key, int[] setFlags) {
        if (key == null) {
            return null;
        }
        
        int low = 0;
        int high = sortedFieldDeserializers.length - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            
            String fieldName = sortedFieldDeserializers[mid].fieldInfo.name;
            
            int cmp = fieldName.compareTo(key);

            if (cmp < 0) {
                low = mid + 1;
            } else if (cmp > 0) {
                high = mid - 1;
            } else {
                if (isSetFlag(mid, setFlags)) {
                    return null;
                }

                return sortedFieldDeserializers[mid]; // key found
            }
        }

        if(this.alterNameFieldDeserializers != null){
            return this.alterNameFieldDeserializers.get(key);
        }
        
        return null;  // key not found.
    }
View Code

 

解析

    // 获取到 Serializer 后,就进行 derialize() 处理了!
    // 流程如下
    // com.alibaba.fastjson.parser.deserializerBeanDeserializer
    public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName, int features) {
        return deserialze(parser, type, fieldName, null, features, null);
    }
    // 一长串的解析动作
    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected <T> T deserialze(DefaultJSONParser parser, // 
                               Type type, // 
                               Object fieldName, // 
                               Object object, //
                               int features, //
                               int[] setFlags) {
        if (type == JSON.class || type == JSONObject.class) {
            return (T) parser.parse();
        }
        // 获取配置, parser 为 DefaultJSONParser
        final JSONLexerBase lexer = (JSONLexerBase) parser.lexer; // xxx
        final ParserConfig config = parser.getConfig();

        int token = lexer.token();
        if (token == JSONToken.NULL) {
            lexer.nextToken(JSONToken.COMMA);
            return null;
        }

        ParseContext context = parser.getContext();
        if (object != null && context != null) {
            context = context.parent;
        }
        ParseContext childContext = null;

        try {
            Map<String, Object> fieldValues = null;

            if (token == JSONToken.RBRACE) {
                lexer.nextToken(JSONToken.COMMA);
                if (object == null) {
                    object = createInstance(parser, type);
                }
                return (T) object;
            }

            if (token == JSONToken.LBRACKET) {
                final int mask = Feature.SupportArrayToBean.mask;
                boolean isSupportArrayToBean = (beanInfo.parserFeatures & mask) != 0 //
                                               || lexer.isEnabled(Feature.SupportArrayToBean) //
                                               || (features & mask) != 0
                                               ;
                if (isSupportArrayToBean) {
                    return deserialzeArrayMapping(parser, type, fieldName, object);
                }
            }

            if (token != JSONToken.LBRACE && token != JSONToken.COMMA) {
                if (lexer.isBlankInput()) {
                    return null;
                }

                if (token == JSONToken.LITERAL_STRING) {
                    String strVal = lexer.stringVal();
                    if (strVal.length() == 0) {
                        lexer.nextToken();
                        return null;
                    }

                    if (beanInfo.jsonType != null) {
                        for (Class<?> seeAlsoClass : beanInfo.jsonType.seeAlso()) {
                            if (Enum.class.isAssignableFrom(seeAlsoClass)) {
                                try {
                                    Enum<?> e = Enum.valueOf((Class<Enum>) seeAlsoClass, strVal);
                                    return (T) e;
                                } catch (IllegalArgumentException e) {
                                    // skip
                                }
                            }
                        }
                    }
                } else if (token == JSONToken.LITERAL_ISO8601_DATE) {
                    Calendar calendar = lexer.getCalendar();
                }

                if (token == JSONToken.LBRACKET && lexer.getCurrent() == ‘]‘) {
                    lexer.next();
                    lexer.nextToken();
                    return null;
                }
                
                StringBuilder buf = (new StringBuilder()) //
                                                        .append("syntax error, expect {, actual ") //
                                                        .append(lexer.tokenName()) //
                                                        .append(", pos ") //
                                                        .append(lexer.pos());

                if (fieldName instanceof String) {
                    buf //
                        .append(", fieldName ") //
                        .append(fieldName);
                }

                buf.append(", fastjson-version ").append(JSON.VERSION);
                
                throw new JSONException(buf.toString());
            }

            if (parser.resolveStatus == DefaultJSONParser.TypeNameRedirect) {
                parser.resolveStatus = DefaultJSONParser.NONE;
            }

            // 解析单个 field
            String typeKey = beanInfo.typeKey;
            for (int fieldIndex = 0;; fieldIndex++) {
                String key = null;
                FieldDeserializer fieldDeser = null;
                FieldInfo fieldInfo = null;
                Class<?> fieldClass = null;
                JSONField feildAnnotation = null;
                boolean customDeserilizer = false;
                if (fieldIndex < sortedFieldDeserializers.length) {
                    fieldDeser = sortedFieldDeserializers[fieldIndex];
                    fieldInfo = fieldDeser.fieldInfo;
                    fieldClass = fieldInfo.fieldClass;
                    feildAnnotation = fieldInfo.getAnnotation();
                    if (feildAnnotation != null && fieldDeser instanceof DefaultFieldDeserializer) {
                        customDeserilizer = ((DefaultFieldDeserializer) fieldDeser).customDeserilizer;
                    }
                }

                boolean matchField = false;
                boolean valueParsed = false;
                // 先根据类型,解析出各字段的字段名
                Object fieldValue = null;
                if (fieldDeser != null) {
                    char[] name_chars = fieldInfo.name_chars;
                    if (customDeserilizer && lexer.matchField(name_chars)) {
                        matchField = true;
                    } else if (fieldClass == int.class || fieldClass == Integer.class) {
                        int intVal = lexer.scanFieldInt(name_chars);
                        if (intVal == 0 && lexer.matchStat == JSONLexer.VALUE_NULL) {
                            fieldValue = null;
                        } else {
                            fieldValue = intVal;
                        }

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        // 如果找不到匹配信息,则跳过就好
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == long.class || fieldClass == Long.class) {
                        long longVal = lexer.scanFieldLong(name_chars);
                        if (longVal == 0 && lexer.matchStat == JSONLexer.VALUE_NULL) {
                            fieldValue = null;
                        } else {
                            fieldValue = longVal;
                        }

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == String.class) {
                        // String 类型直接获取, "code" 字段获取
                        fieldValue = lexer.scanFieldString(name_chars);
                        
                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == java.util.Date.class && fieldInfo.format == null) {
                        fieldValue = lexer.scanFieldDate(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == BigDecimal.class) {
                        fieldValue = lexer.scanFieldDecimal(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == BigInteger.class) {
                        fieldValue = lexer.scanFieldBigInteger(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == boolean.class || fieldClass == Boolean.class) {
                        boolean booleanVal = lexer.scanFieldBoolean(name_chars);

                        if (lexer.matchStat == JSONLexer.VALUE_NULL) {
                            fieldValue = null;
                        } else {
                            fieldValue = booleanVal;
                        }
                        
                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == float.class || fieldClass == Float.class) {
                        float floatVal = lexer.scanFieldFloat(name_chars);
                        if (floatVal == 0 && lexer.matchStat == JSONLexer.VALUE_NULL) {
                            fieldValue = null;
                        } else {
                            fieldValue = floatVal;
                        }

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass == double.class || fieldClass == Double.class) {
                        double doubleVal = lexer.scanFieldDouble(name_chars);
                        if (doubleVal == 0 && lexer.matchStat == JSONLexer.VALUE_NULL) {
                            fieldValue = null;
                        } else {
                            fieldValue = doubleVal;
                        }

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;  
                        }
                    } else if (fieldClass.isEnum() // 
                            && parser.getConfig().getDeserializer(fieldClass) instanceof EnumDeserializer
                            && (feildAnnotation == null || feildAnnotation.deserializeUsing() == Void.class)
                            ) {
                        if (fieldDeser instanceof DefaultFieldDeserializer) {
                            ObjectDeserializer fieldValueDeserilizer = ((DefaultFieldDeserializer) fieldDeser).fieldValueDeserilizer;
                            fieldValue = this.scanEnum(lexer, name_chars, fieldValueDeserilizer);

                            if (lexer.matchStat > 0) {
                                matchField = true;
                                valueParsed = true;
                            } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                                continue;
                            }
                        }
                    } else if (fieldClass == int[].class) {
                        fieldValue = lexer.scanFieldIntArray(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == float[].class) {
                        fieldValue = lexer.scanFieldFloatArray(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (fieldClass == float[][].class) {
                        fieldValue = lexer.scanFieldFloatArray2(name_chars);

                        if (lexer.matchStat > 0) {
                            matchField = true;
                            valueParsed = true;
                        } else if (lexer.matchStat == JSONLexer.NOT_MATCH_NAME) {
                            continue;
                        }
                    } else if (lexer.matchField(name_chars)) {
                        matchField = true;
                    } else {
                        continue;
                    }
                }
                
                if (!matchField) {
                    // 对于复杂泛型的解析,将从 symbolTable 中获取,该 symbolTable 中会以 orderId, name ... 形式呈现
                    key = lexer.scanSymbol(parser.symbolTable);

                    if (key == null) {
                        token = lexer.token();
                        if (token == JSONToken.RBRACE) {
                            lexer.nextToken(JSONToken.COMMA);
                            break;
                        }
                        if (token == JSONToken.COMMA) {
                            if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
                                continue;
                            }
                        }
                    }

                    if ("$ref" == key && context != null) {
                        lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
                        token = lexer.token();
                        if (token == JSONToken.LITERAL_STRING) {
                            String ref = lexer.stringVal();
                            if ("@".equals(ref)) {
                                object = context.object;
                            } else if ("..".equals(ref)) {
                                ParseContext parentContext = context.parent;
                                if (parentContext.object != null) {
                                    object = parentContext.object;
                                } else {
                                    parser.addResolveTask(new ResolveTask(parentContext, ref));
                                    parser.resolveStatus = DefaultJSONParser.NeedToResolve;
                                }
                            } else if ("$".equals(ref)) {
                                ParseContext rootContext = context;
                                while (rootContext.parent != null) {
                                    rootContext = rootContext.parent;
                                }

                                if (rootContext.object != null) {
                                    object = rootContext.object;
                                } else {
                                    parser.addResolveTask(new ResolveTask(rootContext, ref));
                                    parser.resolveStatus = DefaultJSONParser.NeedToResolve;
                                }
                            } else {
                                if (ref.indexOf(‘\\‘) > 0) {
                                    StringBuilder buf = new StringBuilder();
                                    for (int i = 0; i < ref.length(); ++i) {
                                        char ch = ref.charAt(i);
                                        if (ch == ‘\\‘) {
                                            ch = ref.charAt(++i);
                                        }
                                        buf.append(ch);
                                    }
                                    ref = buf.toString();
                                }
                                Object refObj = parser.resolveReference(ref);
                                if (refObj != null) {
                                    object = refObj;
                                } else {
                                    parser.addResolveTask(new ResolveTask(context, ref));
                                    parser.resolveStatus = DefaultJSONParser.NeedToResolve;
                                }
                            }
                        } else {
                            throw new JSONException("illegal ref, " + JSONToken.name(token));
                        }

                        lexer.nextToken(JSONToken.RBRACE);
                        if (lexer.token() != JSONToken.RBRACE) {
                            throw new JSONException("illegal ref");
                        }
                        lexer.nextToken(JSONToken.COMMA);

                        parser.setContext(context, object, fieldName);

                        return (T) object;
                    }

                    if ((typeKey != null && typeKey.equals(key))
                            || JSON.DEFAULT_TYPE_KEY == key) {
                        lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);
                        if (lexer.token() == JSONToken.LITERAL_STRING) {
                            String typeName = lexer.stringVal();
                            lexer.nextToken(JSONToken.COMMA);

                            if (typeName.equals(beanInfo.typeName)|| parser.isEnabled(Feature.IgnoreAutoType)) {
                                if (lexer.token() == JSONToken.RBRACE) {
                                    lexer.nextToken();
                                    break;
                                }
                                continue;
                            }
                            

                            ObjectDeserializer deserializer = getSeeAlso(config, this.beanInfo, typeName);
                            Class<?> userType = null;

                            if (deserializer == null) {
                                Class<?> expectClass = TypeUtils.getClass(type);
                                userType = config.checkAutoType(typeName, expectClass, lexer.getFeatures());
                                deserializer = parser.getConfig().getDeserializer(userType);
                            }

                            Object typedObject = deserializer.deserialze(parser, userType, fieldName);
                            if (deserializer instanceof JavaBeanDeserializer) {
                                JavaBeanDeserializer javaBeanDeserializer = (JavaBeanDeserializer) deserializer;
                                if (typeKey != null) {
                                    FieldDeserializer typeKeyFieldDeser = javaBeanDeserializer.getFieldDeserializer(typeKey);
                                    typeKeyFieldDeser.setValue(typedObject, typeName);
                                }
                            }
                            return (T) typedObject;
                        } else {
                            throw new JSONException("syntax error");
                        }
                    }
                }

                if (object == null && fieldValues == null) {
                    // 按照之前解析好的构造器,初始化一个实例,并作为返回的依据
                    // 找不到类型,则创建 HashMap, 所以 HashMap 是兜底数据结构
                    object = createInstance(parser, type);
                    if (object == null) {
                        fieldValues = new HashMap<String, Object>(this.fieldDeserializers.length);
                    }
                    childContext = parser.setContext(context, object, fieldName);
                    if (setFlags == null) {
                        // 32位一个标记位
                        setFlags = new int[(this.fieldDeserializers.length / 32) + 1];
                    }
                }

                // 找到匹配后,解析
                if (matchField) {
                    if (!valueParsed) {
                        fieldDeser.parseField(parser, object, type, fieldValues);
                    } else {
                        if (object == null) {
                            fieldValues.put(fieldInfo.name, fieldValue);
                        } else if (fieldValue == null) {
                            if (fieldClass != int.class //
                                    && fieldClass != long.class //
                                    && fieldClass != float.class //
                                    && fieldClass != double.class //
                                    && fieldClass != boolean.class //
                                    ) {
                                fieldDeser.setValue(object, fieldValue);
                            }
                        } else {
                            // 将解析出的值放入到 fieldDeser
                            // 使用反射写入 method.invoke(obj, value)
                            // fieldDeser 是对象的 一个字段描述 
                            fieldDeser.setValue(object, fieldValue);
                        }

                        if (setFlags != null) {
                            int flagIndex = fieldIndex / 32;
                            int bitIndex = fieldIndex % 32;
                            setFlags[flagIndex] |= (1 >> bitIndex);
                        }

                        if (lexer.matchStat == JSONLexer.END) {
                            break;
                        }
                    }
                } else {
                    // 如果没有匹配的话,就走字段解析,即递归操作
                    boolean match = parseField(parser, key, object, type, fieldValues, setFlags);
                    if (!match) {
                        if (lexer.token() == JSONToken.RBRACE) {
                            lexer.nextToken();
                            break;
                        }

                        continue;
                    } else if (lexer.token() == JSONToken.COLON) {
                        throw new JSONException("syntax error, unexpect token ‘:‘");
                    }
                }

                // 为下一个字段解析做准备
                if (lexer.token() == JSONToken.COMMA) {
                    continue;
                }

                if (lexer.token() == JSONToken.RBRACE) {
                    lexer.nextToken(JSONToken.COMMA);
                    break;
                }

                if (lexer.token() == JSONToken.IDENTIFIER || lexer.token() == JSONToken.ERROR) {
                    throw new JSONException("syntax error, unexpect token " + JSONToken.name(lexer.token()));
                }
            }

            // 至此fastjson 解析就完成了
            if (object == null) {
                if (fieldValues == null) {
                    object = createInstance(parser, type);
                    if (childContext == null) {
                        childContext = parser.setContext(context, object, fieldName);
                    }
                    return (T) object;
                }

                String[] paramNames = beanInfo.creatorConstructorParameters;
                final Object[] params;
                if (paramNames != null) {
                    params = new Object[paramNames.length];
                    for (int i = 0; i < paramNames.length; i++) {
                        String paramName = paramNames[i];

                        Object param = fieldValues.remove(paramName);
                        if (param == null) {
                            Type fieldType = beanInfo.creatorConstructorParameterTypes[i];
                            FieldInfo fieldInfo = beanInfo.fields[i];
                            if (fieldType == byte.class) {
                                param = (byte) 0;
                            } else if (fieldType == short.class) {
                                param = (short) 0;
                            } else if (fieldType == int.class) {
                                param = 0;
                            } else if (fieldType == long.class) {
                                param = 0L;
                            } else if (fieldType == float.class) {
                                param = 0F;
                            } else if (fieldType == double.class) {
                                param = 0D;
                            } else if (fieldType == boolean.class) {
                                param = Boolean.FALSE;
                            } else if (fieldType == String.class
                                    && (fieldInfo.parserFeatures & Feature.InitStringFieldAsEmpty.mask) != 0) {
                                param = "";
                            }
                        } else {
                            if (beanInfo.creatorConstructorParameterTypes != null && i < beanInfo.creatorConstructorParameterTypes.length) {
                                Type paramType = beanInfo.creatorConstructorParameterTypes[i];
                                if (paramType instanceof Class) {
                                    Class paramClass = (Class) paramType;
                                    if (!paramClass.isInstance(param)) {
                                        if (param instanceof List) {
                                            List list = (List) param;
                                            if (list.size() == 1) {
                                                Object first = list.get(0);
                                                if (paramClass.isInstance(first)) {
                                                    param = list.get(0);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        params[i] = param;
                    }
                } else {
                    FieldInfo[] fieldInfoList = beanInfo.fields;
                    int size = fieldInfoList.length;
                    params = new Object[size];
                    for (int i = 0; i < size; ++i) {
                        FieldInfo fieldInfo = fieldInfoList[i];
                        Object param = fieldValues.get(fieldInfo.name);
                        if (param == null) {
                            Type fieldType = fieldInfo.fieldType;
                            if (fieldType == byte.class) {
                                param = (byte) 0;
                            } else if (fieldType == short.class) {
                                param = (short) 0;
                            } else if (fieldType == int.class) {
                                param = 0;
                            } else if (fieldType == long.class) {
                                param = 0L;
                            } else if (fieldType == float.class) {
                                param = 0F;
                            } else if (fieldType == double.class) {
                                param = 0D;
                            } else if (fieldType == boolean.class) {
                                param = Boolean.FALSE;
                            } else if (fieldType == String.class
                                    && (fieldInfo.parserFeatures & Feature.InitStringFieldAsEmpty.mask) != 0) {
                                param = "";
                            }
                        }
                        params[i] = param;
                    }
                }

                if (beanInfo.creatorConstructor != null) {
                    boolean hasNull = false;
                    if (beanInfo.kotlin) {
                        for (int i = 0; i < params.length; i++) {
                            if (params[i] == null && beanInfo.fields != null && i < beanInfo.fields.length) {
                                FieldInfo fieldInfo = beanInfo.fields[i];
                                if (fieldInfo.fieldClass == String.class) {
                                    hasNull = true;
                                }
                                break;
                            }
                        }
                    }

                    try {
                        if (hasNull && beanInfo.kotlinDefaultConstructor != null) {
                            object = beanInfo.kotlinDefaultConstructor.newInstance(new Object[0]);

                            for (int i = 0; i < params.length; i++) {
                                final Object param = params[i];
                                if (param != null && beanInfo.fields != null && i < beanInfo.fields.length) {
                                    FieldInfo fieldInfo = beanInfo.fields[i];
                                    fieldInfo.set(object, param);
                                }
                            }
                        } else {
                            object = beanInfo.creatorConstructor.newInstance(params);
                        }
                    } catch (Exception e) {
                        throw new JSONException("create instance error, " + paramNames + ", "
                                                + beanInfo.creatorConstructor.toGenericString(), e);
                    }

                    if (paramNames != null) {
                        for (Map.Entry<String, Object> entry : fieldValues.entrySet()) {
                            FieldDeserializer fieldDeserializer = getFieldDeserializer(entry.getKey());
                            if (fieldDeserializer != null) {
                                fieldDeserializer.setValue(object, entry.getValue());
                            }
                        }
                    }
                } else if (beanInfo.factoryMethod != null) {
                    try {
                        object = beanInfo.factoryMethod.invoke(null, params);
                    } catch (Exception e) {
                        throw new JSONException("create factory method error, " + beanInfo.factoryMethod.toString(), e);
                    }
                }

                childContext.object = object;
            }
            // 还可以再用 buildMethod 再修饰一翻, 如果有设置的话
            Method buildMethod = beanInfo.buildMethod;
            if (buildMethod == null) {
                // 因创建时就是 T 类型,所以这里直接强转
                return (T) object;
            }
            
            
            Object builtObj;
            try {
                builtObj = buildMethod.invoke(object);
            } catch (Exception e) {
                throw new JSONException("build object error", e);
            }
            
            return (T) builtObj;
        } finally {
            if (childContext != null) {
                childContext.object = object;
            }
            parser.setContext(context);
        }
    }

    // 解析字段值
    public boolean parseField(DefaultJSONParser parser, String key, Object object, Type objectType,
                              Map<String, Object> fieldValues, int[] setFlags) {
        JSONLexer lexer = parser.lexer; // xxx

        final int disableFieldSmartMatchMask = Feature.DisableFieldSmartMatch.mask;
        FieldDeserializer fieldDeserializer;
        if (lexer.isEnabled(disableFieldSmartMatchMask) || (this.beanInfo.parserFeatures & disableFieldSmartMatchMask) != 0) {
            fieldDeserializer = getFieldDeserializer(key);
        } else {
            fieldDeserializer = smartMatch(key, setFlags);
        }

        final int mask = Feature.SupportNonPublicField.mask;
        if (fieldDeserializer == null
                && (lexer.isEnabled(mask)
                    || (this.beanInfo.parserFeatures & mask) != 0)) {
            if (this.extraFieldDeserializers == null) {
                ConcurrentHashMap extraFieldDeserializers = new ConcurrentHashMap<String, Object>(1, 0.75f, 1);
                for (Class c = this.clazz; c != null && c != Object.class; c = c.getSuperclass()) {
                    Field[] fields = c.getDeclaredFields();
                    for (Field field : fields) {
                        String fieldName = field.getName();
                        if (this.getFieldDeserializer(fieldName) != null) {
                            continue;
                        }
                        int fieldModifiers = field.getModifiers();
                        if ((fieldModifiers & Modifier.FINAL) != 0 || (fieldModifiers & Modifier.STATIC) != 0) {
                            continue;
                        }
                        extraFieldDeserializers.put(fieldName, field);
                    }
                }
                this.extraFieldDeserializers = extraFieldDeserializers;
            }

            Object deserOrField = extraFieldDeserializers.get(key);
            if (deserOrField != null) {
                if (deserOrField instanceof FieldDeserializer) {
                    fieldDeserializer = ((FieldDeserializer) deserOrField);
                } else {
                    Field field = (Field) deserOrField;
                    field.setAccessible(true);
                    FieldInfo fieldInfo = new FieldInfo(key, field.getDeclaringClass(), field.getType(), field.getGenericType(), field, 0, 0, 0);
                    fieldDeserializer = new DefaultFieldDeserializer(parser.getConfig(), clazz, fieldInfo);
                    extraFieldDeserializers.put(key, fieldDeserializer);
                }
            }
        }

        if (fieldDeserializer == null) {
            if (!lexer.isEnabled(Feature.IgnoreNotMatch)) {
                throw new JSONException("setter not found, class " + clazz.getName() + ", property " + key);
            }

            for (FieldDeserializer fieldDeser : this.sortedFieldDeserializers) {
                FieldInfo fieldInfo = fieldDeser.fieldInfo;
                if (fieldInfo.unwrapped //
                        && fieldDeser instanceof DefaultFieldDeserializer) {
                    if (fieldInfo.field != null) {
                        DefaultFieldDeserializer defaultFieldDeserializer = (DefaultFieldDeserializer) fieldDeser;
                        ObjectDeserializer fieldValueDeser = defaultFieldDeserializer.getFieldValueDeserilizer(parser.getConfig());
                        if (fieldValueDeser instanceof JavaBeanDeserializer) {
                            JavaBeanDeserializer javaBeanFieldValueDeserializer = (JavaBeanDeserializer) fieldValueDeser;
                            FieldDeserializer unwrappedFieldDeser = javaBeanFieldValueDeserializer.getFieldDeserializer(key);
                            if (unwrappedFieldDeser != null) {
                                Object fieldObject;
                                try {
                                    fieldObject = fieldInfo.field.get(object);
                                    if (fieldObject == null) {
                                        fieldObject = ((JavaBeanDeserializer) fieldValueDeser).createInstance(parser, fieldInfo.fieldType);
                                        fieldDeser.setValue(object, fieldObject);
                                    }
                                    lexer.nextTokenWithColon(defaultFieldDeserializer.getFastMatchToken());
                                    unwrappedFieldDeser.parseField(parser, fieldObject, objectType, fieldValues);
                                    return true;
                                } catch (Exception e) {
                                    throw new JSONException("parse unwrapped field error.", e);
                                }
                            }
                        } else if (fieldValueDeser instanceof MapDeserializer) {
                            MapDeserializer javaBeanFieldValueDeserializer = (MapDeserializer) fieldValueDeser;

                            Map fieldObject;
                            try {
                                fieldObject = (Map) fieldInfo.field.get(object);
                                if (fieldObject == null) {
                                    fieldObject = javaBeanFieldValueDeserializer.createMap(fieldInfo.fieldType);
                                    fieldDeser.setValue(object, fieldObject);
                                }

                                lexer.nextTokenWithColon();
                                Object fieldValue = parser.parse(key);
                                fieldObject.put(key, fieldValue);
                            } catch (Exception e) {
                                throw new JSONException("parse unwrapped field error.", e);
                            }
                            return true;
                        }
                    } else if (fieldInfo.method.getParameterTypes().length == 2) {
                        lexer.nextTokenWithColon();
                        Object fieldValue = parser.parse(key);
                        try {
                            fieldInfo.method.invoke(object, key, fieldValue);
                        } catch (Exception e) {
                            throw new JSONException("parse unwrapped field error.", e);
                        }
                        return true;
                    }
                }
            }
            
            parser.parseExtra(object, key);

            return false;
        }

        int fieldIndex = -1;
        for (int i = 0; i < sortedFieldDeserializers.length; ++i) {
            if (sortedFieldDeserializers[i] == fieldDeserializer) {
                fieldIndex = i;
                break;
            }
        }
        if (fieldIndex != -1 && setFlags != null && key.startsWith("_")) {
            if (isSetFlag(fieldIndex, setFlags)) {
                parser.parseExtra(object, key);
                return false;
            }
        }

        lexer.nextTokenWithColon(fieldDeserializer.getFastMatchToken());

        // 调用  deserializer.parseField()
        fieldDeserializer.parseField(parser, object, objectType, fieldValues);

        return true;
    }

    // com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer
    @Override
    public void parseField(DefaultJSONParser parser, Object object, Type objectType, Map<String, Object> fieldValues) {
        if (this.fieldValueDeserilizer == null) {
            getFieldValueDeserilizer(parser.getConfig());
        }

        ObjectDeserializer fieldValueDeserilizer = this.fieldValueDeserilizer;
        Type fieldType = fieldInfo.fieldType;
        if (objectType instanceof ParameterizedType) {
            ParseContext objContext = parser.getContext();
            if (objContext != null) {
                objContext.type = objectType;
            }
            if (fieldType != objectType) {
                fieldType = FieldInfo.getFieldType(this.clazz, objectType, fieldType);
                fieldValueDeserilizer = parser.getConfig().getDeserializer(fieldType);
            }
        }

        // ContextObjectDeserializer
        Object value;
        if (fieldValueDeserilizer instanceof JavaBeanDeserializer && fieldInfo.parserFeatures != 0) {
            JavaBeanDeserializer javaBeanDeser = (JavaBeanDeserializer) fieldValueDeserilizer;
            value = javaBeanDeser.deserialze(parser, fieldType, fieldInfo.name, fieldInfo.parserFeatures);
        } else {
            if (this.fieldInfo.format != null && fieldValueDeserilizer instanceof ContextObjectDeserializer) {
                value = ((ContextObjectDeserializer) fieldValueDeserilizer) //
                                        .deserialze(parser,
                                                    fieldType,
                                                    fieldInfo.name,
                                                    fieldInfo.format,
                                                    fieldInfo.parserFeatures);
            } else {
                value = fieldValueDeserilizer.deserialze(parser, fieldType, fieldInfo.name);
            }
        }

        if (value instanceof byte[]
                && ("gzip".equals(fieldInfo.format) || "gzip,base64".equals(fieldInfo.format))) {
            byte[] bytes = (byte[]) value;
            GZIPInputStream gzipIn = null;
            try {
                gzipIn = new GZIPInputStream(new ByteArrayInputStream(bytes));

                ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
                for (;;) {
                    byte[] buf = new byte[1024];
                    int len = gzipIn.read(buf);
                    if (len == -1) {
                        break;
                    }
                    if (len > 0) {
                        byteOut.write(buf, 0, len);
                    }
                }
                value = byteOut.toByteArray();

            } catch (IOException ex) {
                throw new JSONException("unzip bytes error.", ex);
            }
        }

        if (parser.getResolveStatus() == DefaultJSONParser.NeedToResolve) {
            ResolveTask task = parser.getLastResolveTask();
            task.fieldDeserializer = this;
            task.ownerContext = parser.getContext();
            parser.setResolveStatus(DefaultJSONParser.NONE);
        } else {
            if (object == null) {
                fieldValues.put(fieldInfo.name, value);
            } else {
                // 将解析出的字段值放入原对象中, 即 ResponseEntity
                // 此处的字段信息已已知,所以只需要将对象传入即可, fieldInfo.method
                setValue(object, value);
            }
        }
    }

    // com.alibaba.fastjson.parser.deserializer.MapDeserializer
    @SuppressWarnings("unchecked")
    public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
        if (type == JSONObject.class && parser.getFieldTypeResolver() == null) {
            return (T) parser.parseObject();
        }
        
        final JSONLexer lexer = parser.lexer;
        if (lexer.token() == JSONToken.NULL) {
            lexer.nextToken(JSONToken.COMMA);
            return null;
        }

        // 创建空map
        Map<Object, Object> map = createMap(type);

        ParseContext context = parser.getContext();

        try {
            parser.setContext(context, map, fieldName);
            return (T) deserialze(parser, type, fieldName, map);
        } finally {
            parser.setContext(context);
        }
    }
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public Map<Object, Object> createMap(Type type) {
        if (type == Properties.class) {
            return new Properties();
        }

        if (type == Hashtable.class) {
            return new Hashtable();
        }

        if (type == IdentityHashMap.class) {
            return new IdentityHashMap();
        }

        if (type == SortedMap.class || type == TreeMap.class) {
            return new TreeMap();
        }

        if (type == ConcurrentMap.class || type == ConcurrentHashMap.class) {
            return new ConcurrentHashMap();
        }
        
        if (type == Map.class || type == HashMap.class) {
            return new HashMap();
        }
        
        if (type == LinkedHashMap.class) {
            return new LinkedHashMap();
        }

        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;

            Type rawType = parameterizedType.getRawType();
            if (EnumMap.class.equals(rawType)) {
                Type[] actualArgs = parameterizedType.getActualTypeArguments();
                return new EnumMap((Class) actualArgs[0]);
            }
            // 通用map再递归创建, 其实就是创建一个 HashMap
            return createMap(rawType);
        }

        Class<?> clazz = (Class<?>) type;
        if (clazz.isInterface()) {
            throw new JSONException("unsupport type " + type);
        }
        
        try {
            return (Map<Object, Object>) clazz.newInstance();
        } catch (Exception e) {
            throw new JSONException("unsupport type " + type, e);
        }
    }
    
    // 最后,来看 map 是如何解析的吧:分两步, 1. key 的解析; 2. value 的解析
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected Object deserialze(DefaultJSONParser parser, Type type, Object fieldName, Map map) {
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            // key 的类型取第一个 type
            Type keyType = parameterizedType.getActualTypeArguments()[0];
            Type valueType = null;
            if(map.getClass().getName().equals("org.springframework.util.LinkedMultiValueMap")){
                valueType = List.class;
            }else{
                // value 的类型取第二个 type
                valueType = parameterizedType.getActualTypeArguments()[1];
            }
            // 到此,整个 泛型的推导就完成了,后面就是对值的解析了
            if (String.class == keyType) {
                return parseMap(parser, (Map<String, Object>) map, valueType, fieldName);
            } else {
                return parseMap(parser, map, keyType, valueType, fieldName);
            }
        } else {
            return parser.parseObject(map, fieldName);
        }
    }
    
    @SuppressWarnings("rawtypes")
    public static Map parseMap(DefaultJSONParser parser, Map<String, Object> map, Type valueType, Object fieldName) {
        JSONLexer lexer = parser.lexer;

        int token = lexer.token();
        if (token != JSONToken.LBRACE) {
            String msg = "syntax error, expect {, actual " + lexer.tokenName();
            if (fieldName instanceof String) {
                msg += ", fieldName ";
                msg += fieldName;
            }
            msg += ", ";
            msg += lexer.info();

            if (token != JSONToken.LITERAL_STRING) {
                JSONArray array = new JSONArray();
                parser.parseArray(array, fieldName);

                if (array.size() == 1) {
                    Object first = array.get(0);
                    if (first instanceof JSONObject) {
                        return (JSONObject) first;
                    }
                }
            }

            throw new JSONException(msg);
        }

        ParseContext context = parser.getContext();
        try {
            for (int i = 0;;++i) {
                lexer.skipWhitespace();
                char ch = lexer.getCurrent();
                if (lexer.isEnabled(Feature.AllowArbitraryCommas)) {
                    while (ch == ‘,‘) {
                        lexer.next();
                        lexer.skipWhitespace();
                        ch = lexer.getCurrent();
                    }
                }

                String key;
                if (ch == ‘"‘) {
                    // 按 ‘"‘ 进行分隔,得出第一个 key, 即 orderId
                    key = lexer.scanSymbol(parser.getSymbolTable(), ‘"‘);
                    lexer.skipWhitespace();
                    ch = lexer.getCurrent();
                    if (ch != ‘:‘) {
                        throw new JSONException("expect ‘:‘ at " + lexer.pos());
                    }
                } else if (ch == ‘}‘) {
                    lexer.next();
                    lexer.resetStringPosition();
                    lexer.nextToken(JSONToken.COMMA);
                    return map;
                } else if (ch == ‘\‘‘) {
                    if (!lexer.isEnabled(Feature.AllowSingleQuotes)) {
                        throw new JSONException("syntax error");
                    }

                    key = lexer.scanSymbol(parser.getSymbolTable(), ‘\‘‘);
                    lexer.skipWhitespace();
                    ch = lexer.getCurrent();
                    if (ch != ‘:‘) {
                        throw new JSONException("expect ‘:‘ at " + lexer.pos());
                    }
                } else {
                    if (!lexer.isEnabled(Feature.AllowUnQuotedFieldNames)) {
                        throw new JSONException("syntax error");
                    }

                    key = lexer.scanSymbolUnQuoted(parser.getSymbolTable());
                    lexer.skipWhitespace();
                    ch = lexer.getCurrent();
                    if (ch != ‘:‘) {
                        throw new JSONException("expect ‘:‘ at " + lexer.pos() + ", actual " + ch);
                    }
                }

                // key 解析完成后,解析下一个
                lexer.next();
                lexer.skipWhitespace();
                ch = lexer.getCurrent();

                // 重置解析开始
                lexer.resetStringPosition();

                if (key == JSON.DEFAULT_TYPE_KEY && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
                    String typeName = lexer.scanSymbol(parser.getSymbolTable(), ‘"‘);
                    final ParserConfig config = parser.getConfig();

                    Class<?> clazz = config.checkAutoType(typeName, null, lexer.getFeatures());

                    if (Map.class.isAssignableFrom(clazz) ) {
                        lexer.nextToken(JSONToken.COMMA);
                        if (lexer.token() == JSONToken.RBRACE) {
                            lexer.nextToken(JSONToken.COMMA);
                            return map;
                        }
                        continue;
                    }

                    ObjectDeserializer deserializer = config.getDeserializer(clazz);

                    lexer.nextToken(JSONToken.COMMA);

                    parser.setResolveStatus(DefaultJSONParser.TypeNameRedirect);

                    if (context != null && !(fieldName instanceof Integer)) {
                        parser.popContext();
                    }

                    return (Map) deserializer.deserialze(parser, clazz, fieldName);
                }

                Object value;
                lexer.nextToken();

                if (i != 0) {
                    parser.setContext(context);
                }
                
                if (lexer.token() == JSONToken.NULL) {
                    value = null;
                    lexer.nextToken();
                } else {
                    value = parser.parseObject(valueType, key);
                }

                // 是否需要 ResolveFieldDeserializer 处理一遍
                map.put(key, value);
                parser.checkMapResolve(map, key);

                parser.setContext(context, value, key);
                parser.setContext(context);

                final int tok = lexer.token();
                if (tok == JSONToken.EOF || tok == JSONToken.RBRACKET) {
                    return map;
                }

                if (tok == JSONToken.RBRACE) {
                    // 解析完成
                    lexer.nextToken();
                    return map;
                }
            }
        } finally {
            parser.setContext(context);
        }

    }
    
    // com.alibaba.fastjson.parser.JSONLexerBase
    public final String scanSymbol(final SymbolTable symbolTable, final char quote) {
        int hash = 0;

        np = bp;
        sp = 0;
        boolean hasSpecial = false;
        char chLocal;
        for (;;) {
            chLocal = next();

            // 遇到下一个分符则停止, 转义符除外
            if (chLocal == quote) {
                break;
            }

            if (chLocal == EOI) {
                throw new JSONException("unclosed.str");
            }

            // 遇到转义符时,会向后推进一位判定
            if (chLocal == ‘\\‘) {
                if (!hasSpecial) {
                    hasSpecial = true;

                    if (sp >= sbuf.length) {
                        int newCapcity = sbuf.length * 2;
                        if (sp > newCapcity) {
                            newCapcity = sp;
                        }
                        char[] newsbuf = new char[newCapcity];
                        System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
                        sbuf = newsbuf;
                    }

                    // text.getChars(np + 1, np + 1 + sp, sbuf, 0);
                    // System.arraycopy(this.buf, np + 1, sbuf, 0, sp);
                    arrayCopy(np + 1, sbuf, 0, sp);
                }

                chLocal = next();

                switch (chLocal) {
                    case ‘0‘:
                        hash = 31 * hash + (int) chLocal;
                        putChar(‘\0‘);
                        break;
                    case ‘1‘:
                        hash = 31 * hash + (int) chLocal;
                        putChar(‘\1‘);
                        break;
                    case ‘2‘:
                        hash = 31 * hash + (int) chLocal;
                        putChar(‘\2‘);
                        break;
                    case ‘3‘:
                        hash = 31 * hash + (int) chLocal;
                        putChar(‘\3‘);
                        break;
                    case ‘4‘:
                        hash = 31 * hash + (int) chLocal;
                        putChar(‘\4‘);
                        break;
                    case ‘5‘:
                        hash = 31 * hash + (int) chLocal;
                        putChar(‘\5‘);
                        break;
                    case ‘6‘:
                        hash = 31 * hash + (int) chLocal;
                        putChar(‘\6‘);
                        break;
                    case ‘7‘:
                        hash = 31 * hash + (int) chLocal;
                        putChar(‘\7‘);
                        break;
                    case ‘b‘: // 8
                        hash = 31 * hash + (int) ‘\b‘;
                        putChar(‘\b‘);
                        break;
                    case ‘t‘: // 9
                        hash = 31 * hash + (int) ‘\t‘;
                        putChar(‘\t‘);
                        break;
                    case ‘n‘: // 10
                        hash = 31 * hash + (int) ‘\n‘;
                        putChar(‘\n‘);
                        break;
                    case ‘v‘: // 11
                        hash = 31 * hash + (int) ‘\u000B‘;
                        putChar(‘\u000B‘);
                        break;
                    case ‘f‘: // 12
                    case ‘F‘:
                        hash = 31 * hash + (int) ‘\f‘;
                        putChar(‘\f‘);
                        break;
                    case ‘r‘: // 13
                        hash = 31 * hash + (int) ‘\r‘;
                        putChar(‘\r‘);
                        break;
                    case ‘"‘: // 34
                        hash = 31 * hash + (int) ‘"‘;
                        putChar(‘"‘);
                        break;
                    case ‘\‘‘: // 39
                        hash = 31 * hash + (int) ‘\‘‘;
                        putChar(‘\‘‘);
                        break;
                    case ‘/‘: // 47
                        hash = 31 * hash + (int) ‘/‘;
                        putChar(‘/‘);
                        break;
                    case ‘\\‘: // 92
                        hash = 31 * hash + (int) ‘\\‘;
                        putChar(‘\\‘);
                        break;
                    // 16进制数据
                    case ‘x‘:
                        char x1 = ch = next();
                        char x2 = ch = next();

                        int x_val = digits[x1] * 16 + digits[x2];
                        char x_char = (char) x_val;
                        hash = 31 * hash + (int) x_char;
                        putChar(x_char);
                        break;
                    // unicode 编码
                    case ‘u‘:
                        char c1 = chLocal = next();
                        char c2 = chLocal = next();
                        char c3 = chLocal = next();
                        char c4 = chLocal = next();
                        int val = Integer.parseInt(new String(new char[] { c1, c2, c3, c4 }), 16);
                        hash = 31 * hash + val;
                        putChar((char) val);
                        break;
                    default:
                        this.ch = chLocal;
                        throw new JSONException("unclosed.str.lit");
                }
                continue;
            }

            hash = 31 * hash + chLocal;

            if (!hasSpecial) {
                sp++;
                continue;
            }

            if (sp == sbuf.length) {
                putChar(chLocal);
            } else {
                sbuf[sp++] = chLocal;
            }
        }

        token = LITERAL_STRING;

        String value;
        if (!hasSpecial) {
            // return this.text.substring(np + 1, np + 1 + sp).intern();
            int offset;
            if (np == -1) {
                offset = 0;
            } else {
                // 向后推进计算位
                offset = np + 1;
            }
            // 取出相应value
            value = addSymbol(offset, sp, hash, symbolTable);
        } else {
            value = symbolTable.addSymbol(sbuf, 0, sp, hash);
        }

        // 解析下一个做准备, ‘:‘ 分隔符跳过
        sp = 0;
        this.next();

        return value;
    }

    public final String addSymbol(int offset, int len, int hash, final SymbolTable symbolTable) {
        return symbolTable.addSymbol(text, offset, len, hash);
    }
    // com.alibaba.fastjson.parser.SymbolTable
    public String addSymbol(String buffer, int offset, int len, int hash) {
        return addSymbol(buffer, offset, len, hash, false);
    }

    public String addSymbol(String buffer, int offset, int len, int hash, boolean replace) {
        // 根据 hash 定位value, 
        final int bucket = hash & indexMask;

        String symbol = symbols[bucket];
        if (symbol != null) {
            if (hash == symbol.hashCode() // 
                    && len == symbol.length() //
                    && buffer.startsWith(symbol, offset)) {
                return symbol;
            }

            String str = subString(buffer, offset, len);

            if (replace) {
                symbols[bucket] = str;
            }

            return str;
        }
        
        symbol = len == buffer.length() //
            ? buffer //
            : subString(buffer, offset, len);
        symbol = symbol.intern();
        // 没有解析出则现在存入 symbols
        symbols[bucket] = symbol;
        return symbol;
    }


总结:  泛型推断其实很简单:
  1. 普通泛型会被jdk封装为 TypeVariableImpl, 而复合泛型则会被封装为 ParameterizedTypeImpl;
  2. 通过 Class.getGenericSuperclass(), 可以获取完整泛型信息类;
  3. 通过 (ParameterizedType) ((ParameterizedType) superClass).getActualTypeArguments()[0] 可以获取完整泛型;
  4. 通过 ParameterizedType.getRawType() 获取运行时的类信息;
  5. 通过 ParameterizedType.getActualTypeArguments() 获取泛型的内部信息;
  6. 对于多泛型传递导致的类型丢失,在 TypeReference 构造函数传入原始信息,进行对应还原即可;
  7. 当然本文说了很多其他废话;

从fastjson多层泛型嵌套解析,看jdk泛型推断

标签:tcl   md5   这一   click   结果   wired   iter   listt   存在   

原文地址:https://www.cnblogs.com/yougewe/p/10691624.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!