【FastJson源碼分析】爲什麼直接使用JSON.toJSON()枚舉類並沒有被替換成描述

【FastJson源碼分析】爲什麼直接使用JSON.toJSON()枚舉類並沒有被替換成描述

  • 簡述原因
  1. 因爲Json.toJson() 默認取用的是枚舉類的 Name 屬性
  • 如何獲取替換成枚舉類描述的JSON 對象
  1. 使用 JSON.toJSON(JSON.toJSONString(instance)) 獲取

弄清兩者之間的區別,你就知道爲什麼要這樣調用了

JSON.toJSONString()

在研究toJsonString()方法的時候,發現fastjson自己也有一個ObjectSerializer的對象池,當你在實體類中標記了@JSONField註解的時候,它就會根據 實體類的類型返回相對應的ObjectSerializer(序列化器),先看以下代碼:

public final void write(Object object) {
        if (object == null) {
            this.out.writeNull();
        } else {
            Class<?> clazz = object.getClass();
            ObjectSerializer writer = this.getObjectWriter(clazz); //  1 號代碼

            try {
                writer.write(this, object, (Object)null, (Type)null, 0);  // 2號代碼
            } catch (IOException var5) {
                throw new JSONException(var5.getMessage(), var5);
            }
        }
    }
  1. 當實體類中有 @JSONField註解時,1 號代碼中將會返回 JavaBeanSerializer,此時2號代碼將會調用 javaBeanSerializer的write 方法,期間,FieldSerializer會判斷這個Field是不是Enum,如果是,則取 toString的值。關鍵代碼如下:
    if (this.fieldInfo.isEnum) { //here
    	if (this.writeEnumUsingName) {
    		serializer.out.writeString(((Enum)propertyValue).name());
    		return;
    	}
    	if (this.writeEnumUsingToString) {
    		serializer.out.writeString(((Enum)propertyValue).toString());
    		return;
    	}
    }
    
  2. 當實體類中有 @JSONField註解時,1 號代碼中將會返回 ASMSerializer_x_xxx如(ASMSerializer_1_User),估計是在項目初始化的期間通過反射產生的,斷點調試時此時2號代碼會調用Serializable.writeDirect()方法,由於在代碼上這個方法是返回 boolean類型的,且名稱也不對,並沒有對輸出做什麼操作,猜測是使用了Aop技術(具體是什麼沒有做深入研究)。這裏會直接將所有的Field值轉成json格式,而fastjson是默認使用Name屬性的,如本例的(MALE/FEMALE)

JSON.toJSON()

toJson時直接返回name屬性

if (clazz.isEnum()) {
	return ((Enum)javaObject).name();
}

正是這行代碼決定了 JSON.toJSON() 返回的是枚舉類的Name 屬性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章