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[]。这三个参数之所以为可选,是因为它们均有默认配置。

  1. SerializeConfig:序列化配置,我们可以把它理解为一个Map<Class,ObjectSerializer>,它的内部保存着所有被序列化对象的类型,与序列化此对象要使用的ObjectSerializer序列化器之间的映射关系。另外,如果遇到不存在的javaBean类型,它的内部还可以自动创建JavaBeanSerializer(包括直接创建JavaBeanSerializer对象,或者通过asm框架创建ASMJavaBeanSerializer的子类对象)。

  2. SerializeFilter:序列化过滤器???

  3. 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进行序列化的原因。

因此,我们需要关注的重点有三个:

  1. fastjson内部有多少种对象序列化器(即ObjectSerializer有多少个实现类)?

  2. 每种对象序列化器是如何工作的?

  3. 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可识别的类型包括:

  1. 基本类型包装类:Boolean、Character、Byte、Short、Integer、Long、Float、Double

  2. 高精度数:BigDecimal、BigInteger

  3. String

  4. 基本类型的数组:boolean[]、char[]、byte[]、short[]、int[]、long[]、float[]、double[]

  5. Object[]、Class、SimpleDateFormat、Locale、Currency、TimeZone、UUID、InetAddress、Inet4Address、Inet6Address、InetSocketAddress、File、URI、URL、Appendable、StringBuffer、StringBuilder、Pattern、Charset

  6. 原子性对象:AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference、AtomicIntegerArray、AtomicLongArray

  7. 引用对象:WeakReference、SoftReference

  8. awt相关类型:java.awt.Color、java.awt.Font、java.awt.Point、java.awt.Rectangle

  9. jdk8特有类型(java.time包中):LocalDateTime、LocalDate、LocalTime、ZonedDateTime、OffsetDateTime、OffsetTime、ZoneOffset、ZoneRegion、Period、Duration、Instant

  10. oracle特有类型(oracle.sql包中):DATE、TIMESTAMP

另外,fastjson还可以识别一些类型,不光可以识别这些类型,还可以识别这些类型的所有子类。由于不确定这些类具体有多少子类,不可能提前把这些子类的Class对象都添加到map中。因此采取的是,只要某一类型是这些可识别类型或其子类,则即时添加到SerializeConfig中。举个例子:fastjson可以识别所有Map接口的实现类,但不可能提前知道我们自定义的Map接口实现类(如:MyMap.class),所以当遇到这个自定义实现类的时候,才把映射关系添加到map中。

这些可识别的类型包括:

  1. Map接口及其实现类

  2. List接口及其实现类

  3. Collection接口及其实现类

  4. Date及其子类

  5. JSONAware及其实现类

  6. JSONSerializable接口及其实现类

  7. JSONStreamAware接口及其实现类

  8. 枚举类型及其子类

  9. 数组类型

  10. Throwable及其子类

  11. TimeZone及其子类

  12. Appendable及其子类

  13. Charset及其子类

  14. Enumeration及其子类

  15. Calendar及其子类

  16. 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序列化原理详解相关推荐

  1. Redis基础及原理详解

    Redis基础及原理详解 前言:以下是最近学习redis的一些笔记总结,文中如有不当的地方欢迎批评指正,重在记录与学习,笔芯~~ Nosql概述 演进历史 单机mysql Memcached(缓存)+ ...

  2. Java LinkedList的实现原理详解

    LinkedList是Java List类型的集合类的一种实现,此外,LinkedList还实现了Deque接口.本文基于Java1.8,对于LinkedList的实现原理做一下详细讲解. (Java ...

  3. Storm概念、原理详解及其应用(一)BaseStorm

    本文借鉴官文,添加了一些解释和看法,其中有些理解,写的比较粗糙,有问题的地方希望大家指出.写这篇文章,是想把一些官文和资料中基础.重点拿出来,能总结出便于大家理解的话语.与大多数"wordc ...

  4. CRF(条件随机场)与Viterbi(维特比)算法原理详解

    摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...

  5. LVS原理详解(3种工作方式8种调度算法)--老男孩

    一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...

  6. jQuery中getJSON跨域原理详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp28 jQuery中getJSON跨域原理详解 前几天我再开发一个叫 河蟹工 ...

  7. nginx配置文件及工作原理详解

    nginx配置文件及工作原理详解 1 nginx配置文件的结构 2 nginx工作原理 1 nginx配置文件的结构 1)以下是nginx配置文件默认的主要内容: #user nobody; #配置用 ...

  8. EMD算法之Hilbert-Huang Transform原理详解和案例分析

    目录 Hilbert-Huang Transform 希尔伯特-黄变换 Section I 人物简介 Section II Hilbert-Huang的应用领域 Section III Hilbert ...

  9. 图像质量损失函数SSIM Loss的原理详解和代码具体实现

    本文转自微信公众号SIGAI 文章PDF见: http://www.tensorinfinity.com/paper_164.html http://www.360doc.com/content/19 ...

最新文章

  1. 外媒:华为有望最早于2021年推出自动驾驶汽车
  2. oracle9i数据库自动备份,Windows环境下Oracle9i数据库文件的自动备份
  3. canvas 实现图片局部模糊_JavaScript中的图片处理与合成(四)
  4. stylus之方法(Functions)
  5. Scala程序将字符串转换为整数
  6. java 继承重写_java 封装 继承 重写 多态
  7. 【script】python中的函数式编程
  8. 昨天的性能优化与今天的网站故障
  9. python os详解
  10. 在线XML美化格式化工具
  11. 从maya中 导入物体 到Uniyt3D 规范 整理
  12. UNICODE编码UTF-16 中的Endian(FE FF) 和 Little Endian(FF FE)
  13. 对js运算符“||”和“”的总结
  14. 第一次使用码云上传本地项目
  15. python3安装完,出现 No module named '_ssl',解决方案
  16. 雷达模拟器-监控摄像机模拟软件 SPx Video Simulator
  17. 讲一个程序员如何副业月赚三万的真实故事
  18. VMware VMotion迁移与原理
  19. 哈工大计算机学院奖学金,【逆天了】哈工大研究生补贴/奖学金一览表,原来读研福利这么好...
  20. 【Android】使用阿里云直播实现手机直播功能

热门文章

  1. MySQL优化学习总结
  2. 虚拟机+CentOS内核hack7、8、9、17失败记
  3. JSP标准标签库JSTL总结
  4. 人月神话之阅读笔记01
  5. 使用CXF开发WebService程序的总结(一):什么是webservice
  6. FreeBSD上安装Cassandra 3.10
  7. sybase 数据库恢复
  8. Celt Codec简单使用方法
  9. dhcp协议_DHCP(动态主机分配协议)原理
  10. java resume过时方法_学点开发|关于Java多线程用法解析