從fastjson多層泛型嵌套解析,看jdk泛型推斷

  給你一組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 的變化,可使用泛型去適應變化;java

  其次,data下的數據是 key -> object 的結構,若是直接object表示的話,又不友好了。若是不以object表示,針對不一樣的object又如何是好?答案是,再抽象一層泛型出來就好了;android

  最終的數據結構就是這樣: ResponseEntity<T> ---> ResponseEntity<Map<String, T>> , 具體bean就不用寫了吧!git

其實作這一步的解析,仍是容易的。不過,具體怎麼作,就不必定了。web

  另外一個問題,解析這些數據結構,我須要再封裝得簡單點,由於底層的數據訪問步驟都是同樣的,我不想重複造輪子!好比,我只須要在最上層轉入想要轉化的數據結構類型,就能夠獲得不同的數據對象!spring

這個固然很簡單,只須要使用泛型方法就好了。簡單示例以下:json

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,這其實不重要。api

  重要的是,你認爲,如上代碼能成功達到要求嗎???數組

  無論怎麼樣,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. 固然本文說了不少其餘廢話;(json的解析過程)

相關文章
相關標籤/搜索