fastjson序列化原理详解
2019獨角獸企業重金招聘Python工程師標準>>>
所有序列化的API都在JSON類中,方法名稱為toJSONString,或者我們也可以設計自己的序列化方法,代碼如下:
public?class?MyJSON?{public?static?String?toJSONString(Object?object,?SerializeConfig?config,?SerializeFilter[]?filters,SerializerFeature[]?features)?{SerializeWriter?out?=?new?SerializeWriter();try?{//?SerializeConfig可以理解為一個Map<Type,ObjectSerializer>,//?內部保存著類型與對應的對象序列化器之間的映射關系if?(config?==?null)config?=?SerializeConfig.getGlobalInstance();//?核心序列化器,主要負責調用SerializeConfig根據value選擇合適的對象序列化器//?內部還保存著輸出流對象,以及各種過濾器JSONSerializer?serializer?=?new?JSONSerializer(out,?config);//?所有特性最終會合成為一個int值,保存在輸出流對象中if?(features?!=?null)for?(SerializerFeature?feature?:?features)?{serializer.config(feature,?true);}//?如上面所說,過濾器保存在核心序列化器中if?(filters?!=?null?&&?filters.length?>?0)setFilter(serializer,?filters);//?序列化過程的入口方法serializer.write(object);return?out.toString();}?finally?{out.close();}}private?static?void?setFilter(JSONSerializer?serializer,?SerializeFilter...?filters)?{for?(SerializeFilter?filter?:?filters)?{setFilter(serializer,?filter);}}private?static?void?setFilter(JSONSerializer?serializer,?SerializeFilter?filter)?{if?(filter?==?null)?{return;}if?(filter?instanceof?PropertyPreFilter)?{serializer.getPropertyPreFilters().add((PropertyPreFilter)?filter);}if?(filter?instanceof?NameFilter)?{serializer.getNameFilters().add((NameFilter)?filter);}if?(filter?instanceof?ValueFilter)?{serializer.getValueFilters().add((ValueFilter)?filter);}if?(filter?instanceof?PropertyFilter)?{serializer.getPropertyFilters().add((PropertyFilter)?filter);}if?(filter?instanceof?BeforeFilter)?{serializer.getBeforeFilters().add((BeforeFilter)?filter);}if?(filter?instanceof?AfterFilter)?{serializer.getAfterFilters().add((AfterFilter)?filter);}if?(filter?instanceof?LabelFilter)?{serializer.getLabelFilters().add((LabelFilter)?filter);}} }調用方法時需要傳入一個要序列化的目標對象object,以及三個可選參數,分別為SerializeConfig、SerializeFilter[]、SerializerFeature[]。這三個參數之所以為可選,是因為它們均有默認配置。
SerializeConfig:序列化配置,我們可以把它理解為一個Map<Class,ObjectSerializer>,它的內部保存著所有被序列化對象的類型,與序列化此對象要使用的ObjectSerializer序列化器之間的映射關系。另外,如果遇到不存在的javaBean類型,它的內部還可以自動創建JavaBeanSerializer(包括直接創建JavaBeanSerializer對象,或者通過asm框架創建ASMJavaBeanSerializer的子類對象)。
SerializeFilter:序列化過濾器???
SerializerFeature:序列化器特性,主要用于控制序列化過程中的一些行為特性
序列化過程的入口其實就是serializer.write(object);方法的調用,具體執行過程如下:
public?final?void?write(Object?object)?{//?如果value為null則直接輸出"null"并返回if?(object?==?null)?{out.writeNull();return;}//?獲取value對象的類型Class<?>?clazz?=?object.getClass();//?根據Class類型,從SerializeConfig中選擇合適的ObjectSerializerObjectSerializer?writer?=?getObjectWriter(clazz);try?{//?調用ObjectSerializer序列化這個value//?因為輸入的初始value對象沒有與之對應的字段名稱,//?因此第三(字段名稱)和第四(字段類型)兩個參數為nullwriter.write(this,?object,?null,?null,?0);}?catch?(IOException?e)?{throw?new?JSONException(e.getMessage(),?e);}}這就是為什么我說JSONSerializer只負責調用SerializeConfig選擇合適的ObjectSerializer進行序列化的原因。
因此,我們需要關注的重點有三個:
fastjson內部有多少種對象序列化器(即ObjectSerializer有多少個實現類)?
每種對象序列化器是如何工作的?
SerializeConfig中有多少種類型與對象序列化器之間的映射關系
ObjectSerializer接口類圖如下:(點擊可查看放大后的清晰圖片)
整個體系共計61個實現類,以及一個子接口(AutowiredObjectSerializer)
具體每種對象序列化器如何工作,我會單開專題講解,
在SerializeConfig的構造方法中,會添加許多默認支持的映射關系,每個新創建的SerializeConfig對象,都會支持這些類型的序列化。
????????????????put(Boolean.class,?BooleanCodec.instance);put(Character.class,?CharacterCodec.instance);put(Byte.class,?IntegerCodec.instance);put(Short.class,?IntegerCodec.instance);put(Integer.class,?IntegerCodec.instance);put(Long.class,?LongCodec.instance);put(Float.class,?FloatCodec.instance);put(Double.class,?DoubleSerializer.instance);put(BigDecimal.class,?BigDecimalCodec.instance);put(BigInteger.class,?BigIntegerCodec.instance);put(String.class,?StringCodec.instance);put(byte[].class,?ByteArraySerializer.instance);put(short[].class,?ShortArraySerializer.instance);put(int[].class,?IntArraySerializer.instance);put(long[].class,?LongArraySerializer.instance);put(float[].class,?FloatArraySerializer.instance);put(double[].class,?DoubleArraySerializer.instance);put(boolean[].class,?BooleanArraySerializer.instance);put(char[].class,?CharArraySerializer.instance);put(Object[].class,?ObjectArraySerializer.instance);put(Class.class,?ClassSerializer.instance);put(SimpleDateFormat.class,?DateFormatSerializer.instance);put(Locale.class,?LocaleCodec.instance);put(Currency.class,?CurrencyCodec.instance);put(TimeZone.class,?TimeZoneCodec.instance);put(UUID.class,?UUIDCodec.instance);put(InetAddress.class,?InetAddressCodec.instance);put(Inet4Address.class,?InetAddressCodec.instance);put(Inet6Address.class,?InetAddressCodec.instance);put(InetSocketAddress.class,?InetSocketAddressCodec.instance);put(File.class,?FileCodec.instance);put(URI.class,?URICodec.instance);put(URL.class,?URLCodec.instance);put(Appendable.class,?AppendableSerializer.instance);put(StringBuffer.class,?AppendableSerializer.instance);put(StringBuilder.class,?AppendableSerializer.instance);put(Pattern.class,?PatternCodec.instance);put(Charset.class,?CharsetCodec.instance);//?atomicput(AtomicBoolean.class,?AtomicBooleanSerializer.instance);put(AtomicInteger.class,?AtomicIntegerSerializer.instance);put(AtomicLong.class,?AtomicLongSerializer.instance);put(AtomicReference.class,?ReferenceCodec.instance);put(AtomicIntegerArray.class,?AtomicIntegerArrayCodec.instance);put(AtomicLongArray.class,?AtomicLongArrayCodec.instance);put(WeakReference.class,?ReferenceCodec.instance);put(SoftReference.class,?ReferenceCodec.instance);//?awtif?(!awtError)?{try?{put(Class.forName("java.awt.Color"),?ColorCodec.instance);put(Class.forName("java.awt.Font"),?FontCodec.instance);put(Class.forName("java.awt.Point"),?PointCodec.instance);put(Class.forName("java.awt.Rectangle"),RectangleCodec.instance);}?catch?(Throwable?e)?{awtError?=?true;//?skip}}//?jdk8if?(!jdk8Error)?{try?{put(Class.forName("java.time.LocalDateTime"),?Jdk8DateCodec.instance);put(Class.forName("java.time.LocalDate"),?Jdk8DateCodec.instance);put(Class.forName("java.time.LocalTime"),?Jdk8DateCodec.instance);put(Class.forName("java.time.ZonedDateTime"),?Jdk8DateCodec.instance);put(Class.forName("java.time.OffsetDateTime"),?Jdk8DateCodec.instance);put(Class.forName("java.time.OffsetTime"),?Jdk8DateCodec.instance);put(Class.forName("java.time.ZoneOffset"),?Jdk8DateCodec.instance);put(Class.forName("java.time.ZoneRegion"),?Jdk8DateCodec.instance);put(Class.forName("java.time.Period"),?Jdk8DateCodec.instance);put(Class.forName("java.time.Duration"),?Jdk8DateCodec.instance);put(Class.forName("java.time.Instant"),?Jdk8DateCodec.instance);}?catch?(Throwable?e)?{//?skipjdk8Error?=?true;}}if?(!oracleJdbcError)?{try?{put(Class.forName("oracle.sql.DATE"),?DateSerializer.instance);put(Class.forName("oracle.sql.TIMESTAMP"),?DateSerializer.instance);}?catch?(Throwable?e)?{//?skiporacleJdbcError?=?true;}}因此,fastjson預定義的ObjectSerializer可識別的類型包括:
基本類型包裝類:Boolean、Character、Byte、Short、Integer、Long、Float、Double
高精度數:BigDecimal、BigInteger
String
基本類型的數組:boolean[]、char[]、byte[]、short[]、int[]、long[]、float[]、double[]
Object[]、Class、SimpleDateFormat、Locale、Currency、TimeZone、UUID、InetAddress、Inet4Address、Inet6Address、InetSocketAddress、File、URI、URL、Appendable、StringBuffer、StringBuilder、Pattern、Charset
原子性對象:AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference、AtomicIntegerArray、AtomicLongArray
引用對象:WeakReference、SoftReference
awt相關類型:java.awt.Color、java.awt.Font、java.awt.Point、java.awt.Rectangle
jdk8特有類型(java.time包中):LocalDateTime、LocalDate、LocalTime、ZonedDateTime、OffsetDateTime、OffsetTime、ZoneOffset、ZoneRegion、Period、Duration、Instant
oracle特有類型(oracle.sql包中):DATE、TIMESTAMP
另外,fastjson還可以識別一些類型,不光可以識別這些類型,還可以識別這些類型的所有子類。由于不確定這些類具體有多少子類,不可能提前把這些子類的Class對象都添加到map中。因此采取的是,只要某一類型是這些可識別類型或其子類,則即時添加到SerializeConfig中。舉個例子:fastjson可以識別所有Map接口的實現類,但不可能提前知道我們自定義的Map接口實現類(如:MyMap.class),所以當遇到這個自定義實現類的時候,才把映射關系添加到map中。
這些可識別的類型包括:
Map接口及其實現類
List接口及其實現類
Collection接口及其實現類
Date及其子類
JSONAware及其實現類
JSONSerializable接口及其實現類
JSONStreamAware接口及其實現類
枚舉類型及其子類
數組類型
Throwable及其子類
TimeZone及其子類
Appendable及其子類
Charset及其子類
Enumeration及其子類
Calendar及其子類
Clob及其子類
除了以上提到的這些所有類型外,其他類型全部為不可識別類型。對于不可識別的類型,全部使用JavaBeanSerializer或者ASMJavaBeanSerializer的子類(asm動態生成)進行序列化。
SerializeConfig選擇序列化器的邏輯如下:
public?ObjectSerializer?getObjectWriter(Class<?>?clazz)?{//?從已存在的映射關系中,查找序列化器ObjectSerializer?writer?=?get(clazz);//?如果沒有找到if?(writer?==?null)?{try?{//?獲取當前線程使用的類加載器final?ClassLoader?classLoader?=?Thread.currentThread().getContextClassLoader();//?使用類加載器嘗試加載"META-INF/services/com.alibaba.fastjson.serializer.AutowiredObjectSerializer"//?這個文件中保存的所有類(一行一個類的全限定名),并調用無參構造創建對象for?(Object?o?:?ServiceLoader.load(AutowiredObjectSerializer.class,?classLoader))?{//?如果該類沒有實現AutowiredObjectSerializer則忽略if?(!(o?instanceof?AutowiredObjectSerializer))?{continue;}AutowiredObjectSerializer?autowired?=?(AutowiredObjectSerializer)?o;//?把這個序列化器可以處理的類型集合添加到map中for?(Type?forType?:?autowired.getAutowiredFor())?{put(forType,?autowired);}}}?catch?(ClassCastException?ex)?{//?skip}//?再次嘗試獲取對象序列化器writer?=?get(clazz);}//?如果還是沒有找到if?(writer?==?null)?{//?獲取加載JSON類的類加載器final?ClassLoader?classLoader?=?JSON.class.getClassLoader();//?如果當前線程使用的不是這個類加載器,則再次重復上面的步驟if?(classLoader?!=?Thread.currentThread().getContextClassLoader())?{try?{for?(Object?o?:?ServiceLoader.load(AutowiredObjectSerializer.class,?classLoader))?{if?(!(o?instanceof?AutowiredObjectSerializer))?{continue;}AutowiredObjectSerializer?autowired?=?(AutowiredObjectSerializer)?o;for?(Type?forType?:?autowired.getAutowiredFor())?{put(forType,?autowired);}}}?catch?(ClassCastException?ex)?{//?skip}//?再次嘗試獲取writer?=?get(clazz);}}//?如果仍找不到,則進行下面的邏輯處理if?(writer?==?null)?{if?(Map.class.isAssignableFrom(clazz))?{put(clazz,?MapSerializer.instance);}?else?if?(List.class.isAssignableFrom(clazz))?{put(clazz,?ListSerializer.instance);}?else?if?(Collection.class.isAssignableFrom(clazz))?{put(clazz,?CollectionSerializer.instance);}?else?if?(Date.class.isAssignableFrom(clazz))?{put(clazz,?DateSerializer.instance);}?else?if?(JSONAware.class.isAssignableFrom(clazz))?{put(clazz,?JSONAwareSerializer.instance);}?else?if?(JSONSerializable.class.isAssignableFrom(clazz))?{put(clazz,?JSONSerializableSerializer.instance);}?else?if?(JSONStreamAware.class.isAssignableFrom(clazz))?{put(clazz,?JSONStreamAwareSerializer.instance);}?else?if?(clazz.isEnum()?||?(clazz.getSuperclass()?!=?null?&&?clazz.getSuperclass().isEnum()))?{put(clazz,?EnumSerializer.instance);}?else?if?(clazz.isArray())?{Class<?>?componentType?=?clazz.getComponentType();ObjectSerializer?compObjectSerializer?=?getObjectWriter(componentType);put(clazz,?new?ArraySerializer(componentType,?compObjectSerializer));}?else?if?(Throwable.class.isAssignableFrom(clazz))?{put(clazz,?new?ExceptionSerializer(clazz));}?else?if?(TimeZone.class.isAssignableFrom(clazz))?{put(clazz,?TimeZoneCodec.instance);}?else?if?(Appendable.class.isAssignableFrom(clazz))?{put(clazz,?AppendableSerializer.instance);}?else?if?(Charset.class.isAssignableFrom(clazz))?{put(clazz,?CharsetCodec.instance);}?else?if?(Enumeration.class.isAssignableFrom(clazz))?{put(clazz,?EnumerationSeriliazer.instance);}?else?if?(Calendar.class.isAssignableFrom(clazz))?{put(clazz,?CalendarCodec.instance);}?else?if?(Clob.class.isAssignableFrom(clazz))?{put(clazz,?ClobSeriliazer.instance);}?else?{boolean?isCglibProxy?=?false;boolean?isJavassistProxy?=?false;for?(Class<?>?item?:?clazz.getInterfaces())?{if?(item.getName().equals("net.sf.cglib.proxy.Factory")||?item.getName().equals("org.springframework.cglib.proxy.Factory"))?{isCglibProxy?=?true;break;}?else?if?(item.getName().equals("javassist.util.proxy.ProxyObject"))?{isJavassistProxy?=?true;break;}}if?(isCglibProxy?||?isJavassistProxy)?{Class<?>?superClazz?=?clazz.getSuperclass();ObjectSerializer?superWriter?=?getObjectWriter(superClazz);put(clazz,?superWriter);return?superWriter;}if?(Proxy.isProxyClass(clazz))?{put(clazz,?createJavaBeanSerializer(clazz));}?else?{put(clazz,?createJavaBeanSerializer(clazz));}}writer?=?get(clazz);}return?writer;}轉載于:https://my.oschina.net/lixin91/blog/634969
總結
以上是生活随笔為你收集整理的fastjson序列化原理详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一天一种设计模式之五-----代理模式
- 下一篇: Java——容器(Comparable)