【FastJson源碼分析】爲什麼直接使用JSON.toJSON()
枚舉類並沒有被替換成描述
- 簡述原因
- 因爲
Json.toJson()
默認取用的是枚舉類的Name
屬性
- 如何獲取替換成枚舉類描述的
JSON
對象
- 使用
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);
}
}
}
- 當實體類中有
@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; } }
- 當實體類中有
@JSONField
註解時,1 號代碼中將會返回ASMSerializer_x_xxx
如(ASMSerializer_1_User
),估計是在項目初始化的期間通過反射產生的,斷點調試時此時2號代碼會調用Serializable.writeDirect()
方法,由於在代碼上這個方法是返回 boolean類型的,且名稱也不對,並沒有對輸出做什麼操作,猜測是使用了Aop技術(具體是什麼沒有做深入研究)。這裏會直接將所有的Field
值轉成json格式,而fastjson是默認使用Name
屬性的,如本例的(MALE/FEMALE
)
JSON.toJSON()
if (clazz.isEnum()) {
return ((Enum)javaObject).name();
}
正是這行代碼決定了 JSON.toJSON()
返回的是枚舉類的Name 屬性。