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序列化原理详解相关推荐
- Redis基础及原理详解
Redis基础及原理详解 前言:以下是最近学习redis的一些笔记总结,文中如有不当的地方欢迎批评指正,重在记录与学习,笔芯~~ Nosql概述 演进历史 单机mysql Memcached(缓存)+ ...
- Java LinkedList的实现原理详解
LinkedList是Java List类型的集合类的一种实现,此外,LinkedList还实现了Deque接口.本文基于Java1.8,对于LinkedList的实现原理做一下详细讲解. (Java ...
- Storm概念、原理详解及其应用(一)BaseStorm
本文借鉴官文,添加了一些解释和看法,其中有些理解,写的比较粗糙,有问题的地方希望大家指出.写这篇文章,是想把一些官文和资料中基础.重点拿出来,能总结出便于大家理解的话语.与大多数"wordc ...
- CRF(条件随机场)与Viterbi(维特比)算法原理详解
摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...
- LVS原理详解(3种工作方式8种调度算法)--老男孩
一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...
- jQuery中getJSON跨域原理详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp28 jQuery中getJSON跨域原理详解 前几天我再开发一个叫 河蟹工 ...
- nginx配置文件及工作原理详解
nginx配置文件及工作原理详解 1 nginx配置文件的结构 2 nginx工作原理 1 nginx配置文件的结构 1)以下是nginx配置文件默认的主要内容: #user nobody; #配置用 ...
- EMD算法之Hilbert-Huang Transform原理详解和案例分析
目录 Hilbert-Huang Transform 希尔伯特-黄变换 Section I 人物简介 Section II Hilbert-Huang的应用领域 Section III Hilbert ...
- 图像质量损失函数SSIM Loss的原理详解和代码具体实现
本文转自微信公众号SIGAI 文章PDF见: http://www.tensorinfinity.com/paper_164.html http://www.360doc.com/content/19 ...
最新文章
- 外媒:华为有望最早于2021年推出自动驾驶汽车
- oracle9i数据库自动备份,Windows环境下Oracle9i数据库文件的自动备份
- canvas 实现图片局部模糊_JavaScript中的图片处理与合成(四)
- stylus之方法(Functions)
- Scala程序将字符串转换为整数
- java 继承重写_java 封装 继承 重写 多态
- 【script】python中的函数式编程
- 昨天的性能优化与今天的网站故障
- python os详解
- 在线XML美化格式化工具
- 从maya中 导入物体 到Uniyt3D 规范 整理
- UNICODE编码UTF-16 中的Endian(FE FF) 和 Little Endian(FF FE)
- 对js运算符“||”和“”的总结
- 第一次使用码云上传本地项目
- python3安装完,出现 No module named '_ssl',解决方案
- 雷达模拟器-监控摄像机模拟软件 SPx Video Simulator
- 讲一个程序员如何副业月赚三万的真实故事
- VMware VMotion迁移与原理
- 哈工大计算机学院奖学金,【逆天了】哈工大研究生补贴/奖学金一览表,原来读研福利这么好...
- 【Android】使用阿里云直播实现手机直播功能