fastjson源码--进大厂的最后一脚 上

293 阅读32分钟

fastjson源码--进大厂的最后一脚

1.序

记得春招面试的时候的面试官问有读过什么源码没有,自己只是稍微看了一下fastjson的,并且当时最尴尬的是自己对着自己的笔记给面试官读的,然后就顺利的拿下了大厂的offer。所以源码还是值得读的。读源码会让我们有更多的思考在里面,学习的设计思想的魅力。今天就把fastjson整理一下。

2.详细

2.1 JSON

2.1.1 什么是JSON

让我们先来认识一下JSON是什么。以下是百度百科的内容。 在这里插入图片描述 简单来说, Json是一种轻量级的数据交换格式,采用一种“键:值”对的文本格式来存储和表示数据,在系统交换数据过程中常常被使用,是一种理想的数据交换语言。在使用Java做Web开发时,不可避免的会遇到Json的使用。

2.1.2 JSON形式与语法

{
	"ID": 1002,
	"name": "张三",
	"age": 21
}

1:数据在花括号中 2:数据以"键:值"对的形式出现(其中键多以字符串形式出现,值可取字符串,数值,甚至其他json对象) 3:每两个"键:值"对以逗号分隔(最后一个"键:值"对省略逗号) 遵守上面3点,便可以形成一个json对象。

2.1.3 JSON对象数组

[
	{"ID": 1, "name": "张三", "ae": 4},
	{"ID": 2, "name": "李四", "ae": 5},
	{"ID": 3, "name": "王五", "ae": 2}
]

1:数据在方括号中(可理解为数组) 2:方括号中每个数据以json对象形式出现 3:每两个数据以逗号分隔(最后一个无需逗号) 遵守上面3点,便可形成一个json对象数组(及一个数组中,存储了多个json对象) 理解了上面两种基本的形式,我们就可以得出其他的数据形式,例如下面这个:

{
	"部门":"研发部",
	"成员":[
	{"ID": 1001, "name": "张三", "age": 24},
	{"ID": 1002, "name": "李四", "age": 25},
	{"ID": 1003, "name": "王五", "age": 22}],
	"部门位置":"111号"
}

2.1.4 JSON字符串

JSON字符串也是在平时开发中使用较多的,json字符串应满足以下条件: 1:它必须是一个字符串,由" "或者' '包裹数据,支持字符串的各种操作 2:里面的数据格式应该要满足其中一个格式,可以是json对象,也可以是json对象数组或者是两种基本形式的组合变形。

var str = '{ "name": "mady", "age": 24 }';

2.1.5 总

总结:json可以简单的分为基本形式:json对象,json对象数组。两种基本格式组合变形出其他的形式,但其本质还是json对象或者json对象数组中的一种。json对象或对象数组可以转化为json字符串,使用于不同的场合。

2.2 (Jackson,Gson,Fastjson)的对比

2.2.1热度

FastJson
github.com/alibaba/fas… 在这里插入图片描述

Jackson github.com/FasterXML/j… 在这里插入图片描述

Gson github.com/google/gson 在这里插入图片描述

json-lib

2.2.2对比(有待修改)

阿里巴巴的FastJson Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。 无依赖,不需要例外额外的jar,能够直接跑在JDK上。 FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。 FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。 开源的Jackson 相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。 而且Jackson社区相对比较活跃,更新速度也比较快。 Jackson对于复杂类型的json转换bean会出现问题,一些集合Map,List的转换出现问题。 Jackson对于复杂类型的bean转换Json,转换的json格式不是标准的Json格式 Google的Gson Gson是目前功能最全的Json解析神器,Gson当初是为因应Google公司内部需求而由Google自行研发而来, 但自从在2008年五月公开发布第一版后已被许多公司或用户应用。 Gson的应用主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。 而在使用这种对象转换之前需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。 类里面只要有get和set方法,Gson完全可以将复杂类型的json到bean或bean到json的转换,是JSON解析的神器。 Gson在功能上面无可挑剔,但是性能上面比FastJson有所差距。 json-lib json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包, 包括commons-beanutils.jar,commons-collections-3.2.jar,commons-lang-2.6.jar,commons-logging-1.1.1.jar,ezmorph-1.0.6.jar, 对于复杂类型的转换,json-lib对于json转换成bean还有缺陷,比如一个类里面会出现另一个类的list或者map集合,json-lib从json到bean的转换就会出现问题。 json-lib在功能和性能上面都不能满足现在互联网化的需求。

fastjson是目前java语言中最快的json库,比自称最快的jackson速度还要快,第三方独立测试结果看这里: github.com/eishay/jvm-…

2.3 fastjson

2.3.1来源

FastJson
github.com/alibaba/fas… maven中央仓库 central.maven.org/maven2/com/… Sourcefor ge.net sourceforge.net/projects/fa… 在maven项目的pom文件中直接配置fastjson依赖 fastjson最新版本都会发布到maven中央仓库,你可以直接依赖。

<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>x.x.x</version>
</dependency>

下面是fastjson的源码 在这里插入图片描述

2.3.2 Fastjson主要的类和API

在包中,可以发现主要的3个类,JSON,JSONArray,JSONObject。三者之间的关系如下,JSONObject和JSONArray继承JSON。

可以发现, ==JSONObject代表json对象==, ==JSONArray代表json对象数组==, ==JSON代表JSONObject和JSONArray的转化==。

可以发现,JSONObject代表json对象,JSONArray代表json对象数组,JSON代表JSONObject和JSONArray的转化。

Fastjson的主要入口类是com.alibaba.fastjson.JSON 主要的API是JSON.toJSONString 和parseObject。 在这里插入图片描述

序列化 String jsonString = JSON.toJSONString(obj); 反序列化: VO vo = JSON.parseObject("...", VO.class); 泛型反序列化: import com.alibaba.fastjson.TypeReference; List list = JSON.parseObject("...", new TypeReference<List>() {});

2.3.3 源码解析

2.3.3.1 JSONObject

在这里插入图片描述

观察该类的继承与实现关系,不难发现,JSONObject实现了Map接口,而json对象中的数据都是以"键:值"对形式出现,可以猜想,JSONObject底层操作是由Map实现的。

类中主要是get()方法。因为JSONObject相当于json对象,所以该类中主要封装了各种get方法,通过"键:值"对中的键来获取其对应的值。且方法的输入参数几乎皆为String类型,这是因为json对象中,"键:值"对的键都是String类型的。来看一下平时用到较多的 。

1 getString(String key) getString(String key)方法,该方法输入参数为String key(键),输出为String ,用于获取json对象中的字符串型数据。例如通过该方法获取 "name":"bob"键值对中name这个键所对应的值bob。

在这里插入图片描述 在这里插入图片描述

发现内部主要由Map接口中的get()方法实现。 2.getInteger(String key) 再去看JSONObject中另一个常用的方法getInteger(String key),该方法获取json对象中的整型数据,例如获取"age:20"键值对中age对应的整型数值20. 在这里插入图片描述

对比getString(String key)方法,两者极为相似,都是通过Map接口的get()方法实现。 3.其它 在这里插入图片描述

总结:JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取"键:值"对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。

2.3.3.2 JSONArray

在这里插入图片描述

观察JSONArray的继承与实现,并结合上面对JSONObject的分析,不难发现,其内部是由List接口中的方法来完成操作的。 同样观察JSONArray类中的方法,由于方法较多,下面分为两部分

JSONArray代表json对象数组,json数组对象中存储的是一个个json对象,所以类中的方法主要用于直接操作json对象。比如这其中的add(),remove(),containsAll()方法,对应于json对象的添加,删除与判断。其内部主要有List接口中的对应方法来实现。 在这里插入图片描述

跟JSONObject一样,JSONArray里面也有一些get()方法,不过都不常用,最有用的应该是getJSONObject(int index)方法,该方法用于获取json对象数组中指定位置的JSONObject对象,配合size()方法,可用于遍历json对象数组中的各个对象。 接下来

在这里插入图片描述 在这里插入图片描述

通过以上两个方法,在配合for循环,即可实现json对象数组的遍历,当然JSONArray中也实现了迭代器方法来遍历,这和List的遍历极为相似。

在这里插入图片描述

通过遍历得到JSONObject对象,然后再利用JSONObject类中的get()方法,即可实现最终json数据的获取!!!

2.3.3.3 JSON类

最后一个,也是最重要的一个类JSON类。之所以把这个放在最后,是因为这个类主要是实现转化用的,最后的数据获取,还是要通过上面的JSONObject和JSONArray来实现。

在这里插入图片描述 在这里插入图片描述

仔细观察这些方法,主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。 1 toJSONString ()

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

该方法经过多次重载,但最终都是实现json对象转化为json字符串和javabean对象转化为json 字符串。其中,有关键字transient修饰的toJSONString()用于json对象序列化过程中,希望某个"键:值"对数据不变的应用中。 2 parseObject()

JSON类之parseObject()方法,实现json字符串转换为json对象或javabean对象

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

该方法返回JSONObject对象,用于实现json字符串向json对象的转化,其内部调用了parse()方法,调用底层的DefaultJSONParser解析类进行转化,在转化失败时,抛出can not cast to JSONObject异常。

该方法不仅能实现json字符串向json对象的转化,经过重载之后,还能实现json字符串向javabean对象的转化

使用 json字符串与javaBean之间的转换可以使用 TypeReference 这个类,也可以使用Class这个类。

Student stu1=JSON.parseObject(jsonstr,new TypeReference(){}); Student stu1=JSON.parseObject(jsonstr,Student.class);

我推荐使用第二种Class类反射来实现,比较简单。

JSON类之JSONArray()方法,实现json字符串转化为json对象数组或List

与parseObject()方法类似,parseArray()将json字符串转化为json对象数组或转化成包含泛型的List

在这里插入图片描述 在这里插入图片描述 JSON类之toJSON()方法,实现javabean对象转化为json对象

该方法用的比较少,主要用于将javabean对象转化为json对象,内部通过Map,LinkedHashMap,HashMap等集合接口实现。

在这里插入图片描述 在这里插入图片描述 该方法也经过重载,通过TypeReference类和Class类反射来实现,主要讲json对象转化为javabean对象,用的也比较少。

在这里插入图片描述

2.3.4 将对象中的空值输出

在fastjson中,缺省是不输出空值的。无论Map中的null和对象属性中的null,序列化的时候都会被忽略不输出,这样会减少产生文本的大小。但如果需要输出空值怎么做呢?

如果你需要输出空值,需要使用 SerializerFeature.WriteMapNullValue

Model obj = ...; JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue);

class Model { public List items; } 在这里插入图片描述

Model obj = ....;

String text = JSON.toJSONString(obj, SerializerFeature.WriteNullBooleanAsFalse);

2.3.5 Fastjson 处理日期

常规 JSON.toJSONStringWithDateFormat(date, "yyyy-MM-dd HH:mm:ss.SSS");

使用ISO-8601日期格式

JSON.toJSONString(obj, SerializerFeature.UseISO8601DateFormat);

全局修改日期格式 JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd"; JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);

反序列化能够自动识别如下日期格式: ISO-8601日期格式

  • yyyy-MM-dd

  • yyyy-MM-dd HH:mm:ss

  • yyyy-MM-dd HH:mm:ss.SSS

  • 毫秒数字

  • 毫秒数字字符串

  • .NET JSON日期格式

  • new Date(198293238)

public static void main(String[] args) {
        Student student = new Student();
        student.setDate(new Date());

        // 序列化
        String jsonString = JSON.toJSONString(student);
        System.out.println("序列化:" + jsonString);

        // 序列化处理时间,方式一
        jsonString = JSON.toJSONStringWithDateFormat(student, "yyyy-MM-dd HH:mm:ss.SSS");
        System.out.println("序列化处理时间,方式一:" + jsonString);

        // 序列化处理时间,方式二:ISO-8601日期格式
        jsonString = JSON.toJSONString(student, SerializerFeature.UseISO8601DateFormat);
        System.out.println("序列化处理时间,方式二:ISO-8601日期格式:" + jsonString);

        // 序列化处理时间,方式三:全局修改日期格式
        JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
        jsonString = JSON.toJSONString(student, SerializerFeature.WriteDateUseDateFormat);
        System.out.println("序列化处理时间,方式三:全局修改日期格式:" + jsonString);
}

2.3.6 Fastjson 定制序列化

简介 fastjson支持多种方式定制序列化。 通过@JSONField定制序列化 通过@JSONType定制序列化 通过SerializeFilter定制序列化 通过ParseProcess定制反序列化

2.3.6.1使用@JSONField配置

1、JSONField 注解介绍#

package com.alibaba.fastjson.annotation;

public @interface JSONField {
    // 配置序列化和反序列化的顺序,1.1.42版本之后才支持
    int ordinal() default 0;

     // 指定字段的名称
    String name() default "";

    // 指定字段的格式,对日期格式有用
    String format() default "";

    // 是否序列化
    boolean serialize() default true;

    // 是否反序列化
    boolean deserialize() default true;
}

2、JSONField配置方式 可以把@JSONField配置在字段或者getter/setter方法上,例如: 配置在字段上

public class VO {
     @JSONField(name="ID")
     private int id;

     @JSONField(name="birthday",format="yyyy-MM-dd")
     public Date date;
}

配置在 Getter/Setter 上

public class VO {
    private int id;

    @JSONField(name="ID")
    public int getId() { return id;}

    @JSONField(name="ID")
    public void setId(int id) {this.id = id;}
}

注意:若属性是私有的,必须有set*方法。否则无法反序列化。 3、使用format配置日期格式化 可以定制化配置各个日期字段的格式化

public class A {
      // 配置date序列化和反序列使用yyyyMMdd日期格式
      @JSONField(format="yyyyMMdd")
      public Date date;
 }

4、使用serialize/deserialize指定字段不序列化

public class A {
      @JSONField(serialize=false)
      public Date date;
 }

 public class A {
      @JSONField(deserialize=false)
      public Date date;
 }

5、使用ordinal指定字段的顺序 缺省Fastjson序列化一个java bean,是根据fieldName的字母序进行序列化的,你可以通过ordinal指定字段的顺序。这个特性需要1.1.42以上版本。

public static class VO {
    @JSONField(ordinal = 3)
    private int f0;

    @JSONField(ordinal = 2)
    private int f1;

    @JSONField(ordinal = 1)
    private int f2;
}

6、使用serializeUsing制定属性的序列化类 在fastjson 1.2.16版本之后,JSONField支持新的定制化配置

serializeUsing,可以单独对某一个类的某个属性定制序列化,比如:
public static class Student{
    @JSONField(serializeUsing = ModelValueSerializer.class)
    public int value;
}

public static class ModelValueSerializer implements ObjectSerializer {
    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
                      int features) throws IOException {
        Integer value = (Integer) object;
        String text = id+ "号";
        serializer.write(text);
    }
}

测试代码

Student student= new Student();
student.id= 100;
String json = JSON.toJSONString(student);
Assert.assertEquals("{\"value\":\"100号\"}", json);

2.3.6.2使用@JSONType配置

和JSONField类似,但JSONType配置在类上,而不是field或者getter/setter方法上。

SerializeFilter是通过编程扩展的方式定制序列化。fastjson支持6种SerializeFilter,用于不同场景的定制序列化。 PropertyPreFilter 根据PropertyName判断是否序列化 和PropertyFilter不同只根据object和name进行判断,在调用getter之前,这样避免了getter调用可能存在的异常。 public interface PropertyPreFilter extends SerializeFilter {

      boolean apply(JSONSerializer serializer, Object object, String name);
  }

PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化

public interface PropertyFilter extends SerializeFilter {
    boolean apply(Object object, String propertyName, Object propertyValue);
 }

可以通过扩展实现根据object或者属性名称或者属性值进行判断是否需要序列化。例如

PropertyFilter filter = new PropertyFilter() {

    public boolean apply(Object source, String name, Object value) {
        if ("id".equals(name)) {
            int id = ((Integer) value).intValue();
            return id >= 100;
        }
        return false;
    }
};

JSON.toJSONString(obj, filter); // 序列化的时候传入filter NameFilter 修改Key 如果需要修改Key,process返回值则可

public interface NameFilter extends SerializeFilter {
    String process(Object object, String propertyName, Object propertyValue);
}

fastjson内置一个PascalNameFilter,用于输出将首字符大写的Pascal风格。 例如:

public static void main(String[] args) {
            Student student = new Student();
            student.setId(9L);
            student.setName("你好");

            String jsonString = JSON.toJSONString(student);
             // 序列化的时候传入filter
            System.out.println("普通序列化:" + jsonString + "\n");

            NameFilter filter = new NameFilter() {

                @Override
                public String process(Object object, String name, Object value) {
                    System.out.println("----------------object=" + object);
                    System.out.println("----------------name=" + name);
                    System.out.println("----------------value=" + value);
                    System.out.println("");
                    // 属性是id是修改id的名字
                    if ("id".equals(name)) {
                        return name + "$";
                    }
                    return name;
                }
            };

            jsonString = JSON.toJSONString(student, filter);
            // 序列化的时候传入filter
            System.out.println("NameFilter序列化:" + jsonString + "\n");

            // fastjson内置一个PascalNameFilter,用于输出将首字符大写的Pascal风格
            jsonString = JSON.toJSONString(student, new PascalNameFilter());
            // 序列化的时候传入filter
            System.out.println("PascalNameFilter序列化:" + jsonString + "\n");
        }

ValueFilter 修改Value ValueFilter 接口:

public interface ValueFilter extends SerializeFilter {
      Object process(Object object, String propertyName, Object propertyValue);
  }

如果需要修改Value,process返回值则可,例如:

public static void main(String[] args) {
            Student student = new Student();
            student.setId(9L);
            student.setName("你好");

            String jsonString = JSON.toJSONString(student);
             // 序列化的时候传入filter
            System.out.println("普通序列化:" + jsonString + "\n");

            ValueFilter filter = new ValueFilter() {

                @Override
                public Object process(Object object, String name, Object value) {
                    System.out.println("----------------object=" + object);
                    System.out.println("----------------name=" + name);
                    System.out.println("----------------value=" + value);
                    System.out.println("");
                    // 属性是id时修改id的值
                    if ("id".equals(name)) {
                        long id = ((Long) value).longValue();
                        return id + "0";
                    }
                    return value;
                }
            };

            jsonString = JSON.toJSONString(student, filter);
            // 序列化的时候传入filter
            System.out.println("ValueFilter序列化:" + jsonString + "\n");
        }

BeforeFilter 序列化时在最前添加内容 BeforeFilter 接口:

  public abstract class BeforeFilter implements SerializeFilter {
      protected final void writeKeyValue(String key, Object value) { ... }
      // 需要实现的抽象方法,在实现中调用writeKeyValue添加内容
      public abstract void writeBefore(Object object);
  }

在序列化对象的所有属性之前执行某些操作,例如调用 writeKeyValue 添加内容:

public static void main(String[] args) {
            Student student = new Student();
            student.setId(9L);
            student.setName("你好");

            String jsonString = JSON.toJSONString(student);
             // 序列化的时候传入filter
            System.out.println("普通序列化:" + jsonString + "\n");

            BeforeFilter filter = new BeforeFilter() {

                @Override
                public void writeBefore(Object object) {

                    System.out.println("----------------object=" + object);

                    Student student = (Student) object;
                    System.out.println("----------------User.id=" + student.getId() + " " + "User.name=" + student.getName() + "\n");
                    student.setName(student.getName() + "$$$");
                }
            };

            jsonString = JSON.toJSONString(student, filter);
            // 序列化的时候传入filter
            System.out.println("BeforeFilter序列化:" + jsonString + "\n");
        }

AfterFilter 序列化时在最后添加内容 AfterFilter 接口:

  public abstract class AfterFilter implements SerializeFilter {
      protected final void writeKeyValue(String key, Object value) { ... }
      // 需要实现的抽象方法,在实现中调用writeKeyValue添加内容
      public abstract void writeAfter(Object object);
  }

在序列化对象的所有属性之后执行某些操作,例如调用 writeKeyValue 添加内容,例如:

public static void main(String[] args) {
            Student student = new Student();
            student.setId(9L);
            student.setName("你好");

            String jsonString = JSON.toJSONString(student);
             // 序列化的时候传入filter
            System.out.println("普通序列化:" + jsonString + "\n");

            AfterFilter filter = new AfterFilter() {

                @Override
                public void writeAfter(Object object) {

                    Student student = (Student) object;
                    System.out.println("------------Student.id=" + student.getId() + " " + "Student.name=" + student.getName() + "\n");
                    student.setName(student.getName() + "$$$");
                }
            };

            jsonString = JSON.toJSONString(student, filter);
            // 序列化的时候传入filter
            System.out.println("AfterFilter序列化:" + jsonString + "\n");

            jsonString = JSON.toJSONString(student, filter);
            // 序列化的时候传入filter
            System.out.println("BeforeFilter序列化:" + jsonString + "\n");
        }

2.3.7 简单的例子

在这里插入图片描述

2.3.3.1 JSON字符串和JavaBean对象互转

import lombok.Data;

import java.util.ArrayList;
import java.util.List;
@Data
public class Student {
    private Long id;
    private String name;
    private List<Student> users = new ArrayList<Student>();
    public void addStudent(Student student) {
        users.add(student);
    }
}

public class Main {
    public static void main(String[] args) {

        Student student = new Student();
        student.setId(2L);
        student.setName("guest");

        // 转换为 JSON
        String jsonString = JSON.toJSONString(student);
        System.out.println("JSON字符串:" + jsonString);

        // 转换为 对象BEAN
        Student student1 = JSON.parseObject(jsonString, Student.class);
        System.out.println("JavaBean对象:" + student1);
    }
}

2.3.3.2 JSON字符串转JSON对象

public class Main1 {
    public static void main(String[] args) {
        String s ="{\"student\":\"study\",\"id\":\"1\",\"ordinal\":8,\"organUnitFullName\":\"testJSON\",\"parent\":\"0\",\"suborderNo\":\"58961\"}";

        JSONObject jsonObject = JSON.parseObject(s);
        String study = jsonObject.getString("student");
        String id = jsonObject.getString("id");

        System.out.println("study ="+study);
        //add
        System.out.println("id ="+id);
        //1
        System.out.println("jsonObject ="+jsonObject);
        //action =add
        //id =1
    }

}

2.3.3.3 JSON字符串数组类型与JAVA对象互转

{
	"errors":
		[
			{
				"code": "UUM70004",
				"message": "名称不能为空",
				"data": {
					"id": "254",
					"name": "liu",
				},
				"success": false
			}, {
				"code": "UUM70004",
				"message": "名称不能为空",
				"data": {
					"id": "255",
					"name": "liu",
				},
				"success": false
			}
		]
}

public static void main(String[] args) {
        //json字符串--数组型与JSONArray对象之间的转换
        String str = "{\"errors\":[{\"code\":\"UUM70004\",\"message\":\"名称不能为空\",\"data\":{\"id\":\"254\",\"name\":\"liu\"},\"success\":false},{\"code\":\"UUM70004\",\"message\":\"名称不能为空\",\"data\":{\"id\":\"255\",\"name\":\"liu\"},\"success\":false}]}";
        JSONObject jsonObject = JSON.parseObject(str);
        JSONArray error = jsonObject.getJSONArray("errors");
        List<ErrEor> errors = JSON.parseObject(error.toJSONString(), new TypeReference<List<ErrEor>>() {
        });
        for (ErrEor e: errors) {
            //Error的属性
            System.out.println("Error属性="+e.getSuccess());
            System.out.println("Error属性="+e.getCode());
            System.out.println("Error属性="+e.getMessage());
            //Error集合属性
            List<Data> datas =  e.getData();
            for (Data d: datas) {
                System.out.println("data对象属性=" + d.getId());
                System.out.println("data对象属性=" + d.getName());
            }
        }
    }


2.3.3.4 JAVA对象转JSON对象

    //javabean转json对象
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("liu");
        student.setId(2L);

        JSONObject jsonObj = (JSONObject) JSON.toJSON(student);
        JSON json = (JSON) JSON.toJSON(student);
        System.out.println("jsonObj"+jsonObj);
        System.out.println("json对象"+json);
    }

2.3.3.5 总结

(1)对于JSON对象与JSON格式字符串的转换可以直接用 toJSONString()这个方法。 (2)javaBean与JSON格式字符串之间的转换要用到:JSON.toJSONString(obj); (3)javaBean与json对象间的转换使用:JSON.toJSON(obj),然后使用强制类型转换,JSONObject或者JSONArray。

2.3.8 序列化和反序列化源码详解

序列化是通过某种算法将存储于内存中的对象转换成可以用于持久化存储或者通信的形式的过程 反序列化是将这种被持久化存储或者通信的数据通过对应解析算法还原成对象的过程,它是序列化的逆向操作

1为什么需要序列化

前端请求后端接口数据的时候,后端需要返回 JSON 数据,这就是后端将 Java 堆中的对象序列化为了 JSON 数据传给前端,前端可以根据自身需求直接使用或者将其反序列化为 JS 对象。 2怎么序列化 (1)将对象实例相关的类元数据输出。 (2)递归地输出类的超类描述直到不再有超类。 (3)类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。 (4)从上至下递归输出实例的数据 3 JDK类库中序列化反序列化 序列化 步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流: ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\object.out")); 步骤二:通过对象输出流的writeObject()方法写对象: oos.writeObject(new User("xuliugen", "123456", "male")); 反序列化 步骤一:创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流: ObjectInputStream ois= new ObjectInputStream(new FileInputStream("object.out")); 步骤二:通过对象输出流的readObject()方法读取对象: User user = (User) ois.readObject(); 说明:为了正确读取数据,完成反序列化,必须保证向对象输出流写对象的顺序与从对象输入流中读对象的顺序一致。

2.3.8.1 序列化过程

在这里插入图片描述 fastjson核心功能包括序列化和反序列化,序列化的含义是将java对象转换成跨语言的json字符串。

在这里,需要考虑的主要有两个部分,一是临时保存在序列化过程中用于储存数据的容器,二是处理对象序列化的序列化器。 在fastjson中,保存数据的容器使用了wirter,字符输出流,而且是自实现的一个字符输出流。相对原来的writer,追加了很多需要输出的信息的实现,比如输出一个字符串,输出一个字符,输出一个long类型数据等。而处理对象序列化的序列化器,而使用了责任链模式和工厂模式,将不同类型的java对象分散到不同的序列化器当中。而每个序列化器只处理与自身类型相对应的数据信息,这样就避免了在处理时,各种情况交织在一块,逻辑混乱的问题。 下面就源码本身作一个分析,其中结合两个部分进行分析。

SerializeWriter数据保存器(序列化输出容器) com.alibaba.fastjson.serializer.SerializeWriter类非常重要,序列化输出都是通过转换底层操作,

在这里插入图片描述 继承了Writer类,实现了输出字符的基本功能,并且提供了拼接数据的基本功能。内部使用了一个buf数组和count来进行计数。这个类的实现结果和StringBuilder的工作模式差不多。但我们说为什么不使用StringBuilder,主要是因为StringBuilder没有针对json序列化提出更加有效率的处理方式,而且单就StringBuilder而言,内部是为了实现字符串拼接而生,因为很自然地使用了更加能够读懂的方式进行处理。相比,serializeWriter单处理json序列化数据传输,功能单一,因此在某些方面更加优化一些。

SerializeWriter是一个用于储存在序列化过程中产生的数据信息,它与jdk中的StringBuiler有着类似的功能,即将不同的数据填充到此容器中。之所以不使用StringBuilder的原因之一在于StringBuilder没有提供一些特别为性能优化的方法,并且StringBuilder在处理过程中增加了多余的操作(如新分配对象)。该容器的主要功能就是接收不同的数据,并将这些数据存储到该内部的一个字符数组当中,同时记录字符总数。

既然充当了一个数据输出的角色,那么就可以往其中输入任何的数据,包括int,byte,short等基本类型和对应的包装类型,也包括日期数据,以及经常使用的字符串数据等。对于在这些数据类型之外的其它类型,由于json的特殊结构,所有的高级类型均可以转化于这些基础类型的组织体,所以不需要再针对高级类型作处理了(这些是序列化器应该考虑的问题)。

在这里插入图片描述 方法总共可以分五个部分, 1.第一个部分是针对writer基本功能一个扩展,即支持输出int,字符,以及字符数组,追加字符数组(包括字符串)等; 2.第二个部分提供了写整形和长整形的基本方法; 3.第三个部分是提供写基本数据类型数组的支持; 4.第四个部分是提供写一个数字+一个字符的形式,比如数据+[,],}]这种格式;第五个部分是提供写数据串,主是是针对字符串追加双引号或单引号(以支持标准json)。 5.五个部分的方法,每个部分都有其特殊的作用和意义,针对最常用的数字和字符串作了特别的对待。 在实现上面,SerializeWriter使用了一个内部的字符数组作为数据的储存器,同时使用了一个计数器计算当前存储的字符量。既然使用了字符数组,那么肯定有相关的操作,如字符扩容等。整个写数据的过程,其实就是往这个字符数组追加数据的过程,需要考虑只是如何追加数据的问题,即上面所列出的这么多些方法。在最终写完数据之后,即可将这个字符数组转为我们所需要的字符串了。

源码

/**
     * @since 1.2.9
     * @param writer
     * @param defaultFeatures
     * @param features
     */

    protected char                           buf[];
    /**
     * 储存序列化结果的字段
     */
    protected int                            count;
    /**
     * 写入缓存的长度
     */
    private final static ThreadLocal<char[]> bufLocal         = new ThreadLocal<char[]>();
    /**
     * 该对象用于close时将buf绑定到线程上,避免下次重复new出
     */
    protected int                            features;
    /**
     * 序列化的一些特性配置
     */
    private final Writer                     writer;
    /**
     * 包装对象,支持对Writer类型包含数据的序列化
     */

    //传入Writer对象
    public SerializeWriter(Writer writer, int defaultFeatures, SerializerFeature... features){
        this.writer = writer;
        buf = bufLocal.get();
        //获取线程缓存buf对象
        if (buf != null) {
            bufLocal.set(null);
        } else {
            buf = new char[2048];
        }
        //获取到赋值给当前buf并清空,防止重复new出。
        //由于count在关闭的时候已经等于0,所以即使buf里有数据,也不会影响当次结果
        int featuresValue = defaultFeatures;
        //默认序列化属性
        for (SerializerFeature feature : features) {
            featuresValue |= feature.getMask();
        }
        this.features = featuresValue;

        computeFeatures();
    }

在类声明中,这里有一个优化措施(笔者最开始未注意到,经作者指出之后才明白)。即是对buf数组的缓存使用,即在一次处理完毕之后,储存的数据容器并不销毁,而是留在当前线程变量中。以便于在当前线程中再次序列化json时使用。源码如下:

public SerializeWriter(){
        buf = bufLocal.get(); // new char[1024];
        if (buf == null) {
            buf = new char[1024];
        } else {
            bufLocal.set(null);
        }
    }

在初始构造时,会从当前线程变量中取buf数组并设置在对象属性buf中。而在每次序列化完成之后,会通过close方法,将此buf数组再次绑定在线程变量当中,如下所示:

/**
     * Close the stream. This method does not release the buffer, since its contents might still be required. Note:
     * Invoking this method in this class will have no effect.
     */
    public void close() {
        bufLocal.set(buf);
    }

当然,buf重新绑定了,肯定计数器count应该置0。这是自然,count是对象属性,每次在新建时,自然会置0。

在实现过程当中,很多具体的实现是借鉴了StringBuilder的处理模式的,在以下的分析中会说到。

存在buf的缓存对象,自然需要具体的写入方法。下图列出了主要的写入方法

在这里插入图片描述 总结 SerializeWriter主要实现了五个方面的输出内容。 1,提供writer的基本功能,输出字符,输出字符串 2,提供对整形和长整形输出的特殊处理 3,提供对基本类型数组输出的支持 4,提供对整形+字符的输出支持 5,提供对字符串+双(单)引号的输出方式 五个方面主要体现在不同的作用域。 1,第一个提供了最基本的writer功能,以及在输出字符上最基本的功能,即拼接字符数组(不是字符串); 2,第二个针对最常用的数字进行处理; 3,第三个,针对基本类型数组类处理; 4,第四个针对在处理集合/数组时,最后一位的特殊处理,联合了输出数字和字符的双重功能,效率上比两个功能的实现原理上更快一些; 5,第五个,针对字符串的特殊处理(主要是特殊字符处理)以及在json中,字符串的引号处理(即在json中,字符串必须以引号引起来)。 实现思想 数据输出最后都变成了拼接字符的功能,即将各种类型的数据转化为字符数组的形式,然后将字符数组拼接到buf数组当中。这中间主要逻辑如下: 1 对象转化为字符数组 2 准备装载空间,以容纳数据 2.1 计数器增加 2.2 扩容,字符数组扩容 3 装载数据 4 计数器计数最新的容量,完成处理 这里面主要涉及到一个buf数组扩容的概念,其使用的扩容函数expandCapacity其内部实现和StringBuilder中一样。即(当前容量 + 1)* 2,具体可以见相应函数或StringBuilder.ensureCapacityImpl函数。

JsonSerializer( 对象序列化入口)

在这里插入图片描述 JsonSerializer,准备地讲,这个类不应该叫这个名字,因为它与其它的对象序列化器相混淆了。这只是一个提供对象序列化的一个入口;同时,它持有所有具体负责对象序列化工作类的引用。将这些序列化器集中起来,需要用到哪个对象序列化器时,就取出这个序列化器,并调用相应的序列化方法。

既然是对象序列化入口,它就需要关注两个事情。一是我们究竟有哪些序列化器可以使用,二是对于一个对象,应该使用哪一个序列化器来进行工作。对于这两个问题,JsonSerializer内部持有一个JSONSerializerMap的属性,即表示应该序列化的对象类型和对应的序列化器的一个映射。我们来看默认的构造方法,它使用了默认的全局对象类型和对象序列化器映射:

这些序列化器,覆盖了基本数据,字符串类型,日期,以及集合,map,以及javaBean的所有序列化器。因为不存在没有匹配不了的序列化器。既然有个序列化器,就可以执行序列化工作了。即到了序列化入口应该做的工作了。

Class<?> clazz = object.getClass(); ObjectSerializer writer = getObjectWriter(clazz); writer.write(this, object);

首先获得当前序列化对象所在的类型,再根据类型取得相对应的序列化器,最后使用序列化器进行正式的序列化工作。

Write 正如上面所说,进入序列化工作之后,即是针对每一种类型进行序列化处理了。该序列化工作使用了统一的方法,即实现了统一的序列化方法: void write(JSONSerializer serializer, Object object) throws IOException

该方法在抽象类(可以说是接口)ObjectSerializer中定义,即所有的序列化器都继承了此类,并实现了此方法用于处理不同的情形。对于上层调用(如JsonSerializer),不需要考虑每一个类型的序列化工作是如何实现的,只需要针对不同的类型找到正确的序列化器,进行序列化工作即可。

对于一个序列化器,通常的工作,是首先取得当前的数据储存容器,然后根据不同的对象类型,将对象输出到outWriter中即可。比如一个序列化实现IntergerSerializer,它的实现如下:

SerializeWriter out = serializer.getWrier(); Integer value = (Integer) object; out.writeInt(value.intValue());

这样即完成了一个完整的序列化工作。当然,对于复杂的数据类型,在实现过程中,可能需要递归地调用JsonSerializer的序列化工作,这得归结于如何处理不同的对象类型了。比如处理一个对象集合时,除需要处理集合本身之外,还需要处理集合中的每一个对象,这时又是一个解析过程。由于使用了同一个jsonSerializer,所以在进行数据处理时,输出的数据会按照在解析过程中的顺序,顺序地写入到outWriter中,这样即保证了数据的正确性。

具体序列化过程

关键步骤 1 SerializeWriter out = new SerializeWriter(); //和StringBuilder 一样,并且在存储过程中进行了性能优化(数据保持器) 2 JSONSerializer serializer = new JSONSerializer(out); //提供一个对象序列化的入口 //哪些序列化器可以使用 //对于一个对象应该使用哪一个来进行序列化 3 serializer.write(object) //调用序列化方法序列化对象,产生JSON字符串信息 4 return out.toString(); //返回JSON

从调用方法toJSONString开始,会调用

public static final String toJSONString(Object object, SerializerFeature... features) {
        SerializeWriter out = new SerializeWriter();
        //详细写数据的类,存储序列化过程的数据,最后通过 out.toString()转化为json字符串
        try {
            JSONSerializer serializer = new JSONSerializer(out);
            //Json序列化解析对象的类,解析过程中向out写入数据
            serializer.getPropertyFilters().add(new PropertyFilter() {
                
                public boolean apply(Object source, String name, Object value) {
                    if ("id".equals(name)) {
                        return false;
                    }
                    return true;
                }
            });
            serializer.getNameFilters().add(new NameFilter() {

                public String process(Object source, String name, Object value) {
                    if ("v".equals(name)) {
                        return "value";
                    }
                    return name;
                }
                
            });
            serializer.getValueFilters().add(new ValueFilter() {
                
                public Object process(Object source, String name, Object value) {
                    if ("v".endsWith(name)) {
                        return "xxx";
                    }
                    
                    return value;
                }
            });
            for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
                //向解析器添加序列化属性
                serializer.config(feature, true);
            }
            serializer.write(object);
            //解析传入的对象,保存在out中
            return out.toString();
            //将解析的结果转成String输出
        } catch (StackOverflowError e) {
            throw new JSONException("maybe circular references", e);
        } finally {
            out.close();
        }
}

接下里我们来看JSONSerializer的write方法

/**
    * @Description
    * 这个序列化方法实际并不是真正执行序列化操作,首先做序列化特性配置,
    * 然后追加序列化拦截器,开始执行序列化对象操作委托给了config对象查找。
    * 我们继续进入serializer.write(object) 查看:
    */
public final void write(Object object) {
        //如果空对象,直接写入null字符串Z
        if (object == null) {
            out.writeNull();
            return;
        }

        Class<?> clazz = object.getClass();
        ObjectSerializer writer = getObjectWriter(clazz);
        //获取到类,通过getObjectWriter(clazz)找到对应的解析器
        try {
            writer.write(this, object, null, null, 0);
            //对应序列化器执行序列化写操作
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
}

那我们来看看怎么获取对应序列化器的

 * 内部又调用com.alibaba.fastjson.serializer.SerializeConfig#
     * getObjectWriter(java.lang.Class < ? >, boolean),这个类实现相对复杂了一些,
     * 我会按照代码顺序梳理所有序列化实例的要点 :
     *
     * 查找具体序列化实例,查找方法基本思想根据class类型或者实现接口类型进行匹配查找。
     * 接下来针对逐个序列化实现依次分析。
	 */
	public ObjectSerializer getObjectWriter(Class<?> clazz, boolean create) {
        /** 首先从内部已经注册查找特定class的序列化实例 */
	    ObjectSerializer writer = get(clazz);
        //如果未获取到,再解析对象类型,并加入配置列表当中,例如
        if (writer == null) {
            try {
                final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                /** 使用当前线程类加载器 查找 META-INF/services/AutowiredObjectSerializer.class实现类 */
                for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {
                    if (!(o instanceof AutowiredObjectSerializer)) {
                        continue;
                    }

                    AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
                    for (Type forType : autowired.getAutowiredFor()) {
                        //如果存在,注册到内部serializers缓存中
                        put(forType, autowired);
                    }
                }
            } catch (ClassCastException ex) {
                // skip
            }

            writer = get(clazz);
        }

        if (writer == null) {
            final ClassLoader classLoader = JSON.class.getClassLoader();
            /** 使用加载JSON类的加载器 查找 META-INF/services/AutowiredObjectSerializer.class实现类 */
            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()) {
                            //如果存在,注册到内部serializers缓存中
                            put(forType, autowired);
                        }
                    }
                } catch (ClassCastException ex) {
                    // skip
                }
                //尝试在已注册缓存找到特定class的序列化实例
                writer = get(clazz);
            }
        }

        for (Module module : modules) {
            writer = module.createSerializer(this, clazz);
            if (writer != null) {
                put(clazz, writer);
                return writer;
            }
        }
        
        if (writer == null) {
            String className = clazz.getName();
            Class<?> superClass;

            if (Map.class.isAssignableFrom(clazz)) {
                //如果class实现类Map接口,使用MapSerializer序列化
                put(clazz, writer = MapSerializer.instance);
            } else if (List.class.isAssignableFrom(clazz)) {
                //如果class实现类List接口,使用ListSerializer序列化
                put(clazz, writer = ListSerializer.instance);
            } else if (Collection.class.isAssignableFrom(clazz)) {
                //如果class实现类Collection接口,使用CollectionCodec序列化
                put(clazz, writer = CollectionCodec.instance);
            } else if (Date.class.isAssignableFrom(clazz)) {
                //如果class继承Date,使用DateCodec序列化
                put(clazz, writer = DateCodec.instance);
            } else if (JSONAware.class.isAssignableFrom(clazz)) {
                //如果class实现类JSONAware接口,使用JSONAwareSerializer序列化
                put(clazz, writer = JSONAwareSerializer.instance);
            } else if (JSONSerializable.class.isAssignableFrom(clazz)) {
                //如果class实现类JSONSerializable接口,使用JSONSerializableSerializer序列化
                put(clazz, writer = JSONSerializableSerializer.instance);
            } else if (JSONStreamAware.class.isAssignableFrom(clazz)) {
                //如果class实现类JSONStreamAware接口,使用MiscCodecr序列化
                put(clazz, writer = MiscCodec.instance);
            } else if (clazz.isEnum()) {
                JSONType jsonType = TypeUtils.getAnnotation(clazz, JSONType.class);
                if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                    /** 如果是枚举类型,并且启用特性 serializeEnumAsJavaBean
                     *  使用JavaBeanSerializer序列化(假设没有启用asm)
                     */
                    put(clazz, writer = createJavaBeanSerializer(clazz));
                } else {
                    /** 如果是枚举类型,没有启用特性 serializeEnumAsJavaBean
                     *  使用EnumSerializer序列化
                     */
                    put(clazz, writer = EnumSerializer.instance);
                }
            } else if ((superClass = clazz.getSuperclass()) != null && superClass.isEnum()) {
                JSONType jsonType = TypeUtils.getAnnotation(superClass, JSONType.class);
                if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                    /** 如果父类是枚举类型,并且启用特性 serializeEnumAsJavaBean
                     *  使用JavaBeanSerializer序列化(假设没有启用asm)
                     */
                    put(clazz, writer = createJavaBeanSerializer(clazz));
                } else {
                    /** 如果父类是枚举类型,没有启用特性 serializeEnumAsJavaBean
                     *  使用EnumSerializer序列化
                     */
                    put(clazz, writer = EnumSerializer.instance);
                }
            } else if (clazz.isArray()) {
                Class<?> componentType = clazz.getComponentType();
                ObjectSerializer compObjectSerializer = getObjectWriter(componentType);
                put(clazz, writer = new ArraySerializer(componentType, compObjectSerializer));
            } else if (Throwable.class.isAssignableFrom(clazz)) {
                SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy);
                beanInfo.features |= SerializerFeature.WriteClassName.mask;
                put(clazz, writer = new JavaBeanSerializer(beanInfo));
            } else if (TimeZone.class.isAssignableFrom(clazz) || Map.Entry.class.isAssignableFrom(clazz)) {
                put(clazz, writer = MiscCodec.instance);
            } else if (Appendable.class.isAssignableFrom(clazz)) {
                put(clazz, writer = AppendableSerializer.instance);
            } else if (Charset.class.isAssignableFrom(clazz)) {
                put(clazz, writer = ToStringSerializer.instance);
            } else if (Enumeration.class.isAssignableFrom(clazz)) {
                put(clazz, writer = EnumerationSerializer.instance);
            } else if (Calendar.class.isAssignableFrom(clazz) //
                    || XMLGregorianCalendar.class.isAssignableFrom(clazz)) {
                put(clazz, writer = CalendarCodec.instance);
            } else if (TypeUtils.isClob(clazz)) {
                put(clazz, writer = ClobSeriliazer.instance);
            } else if (TypeUtils.isPath(clazz)) {
                put(clazz, writer = ToStringSerializer.instance);
            } else if (Iterator.class.isAssignableFrom(clazz)) {
                put(clazz, writer = MiscCodec.instance);
            } else if (org.w3c.dom.Node.class.isAssignableFrom(clazz)) {
                put(clazz, writer = MiscCodec.instance);
            } else {
                if (className.startsWith("java.awt.") //
                    && AwtCodec.support(clazz) //
                ) {
                    // awt
                    if (!awtError) {
                        try {
                            String[] names = new String[]{
                                    "java.awt.Color",
                                    "java.awt.Font",
                                    "java.awt.Point",
                                    "java.awt.Rectangle"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    put(Class.forName(name), writer = AwtCodec.instance);
                                    return writer;
                                }
                            }
                        } catch (Throwable e) {
                            awtError = true;
                            // skip
                        }
                    }
                }
                
                // jdk8
                if ((!jdk8Error) //
                    && (className.startsWith("java.time.") //
                        || className.startsWith("java.util.Optional") //
                        || className.equals("java.util.concurrent.atomic.LongAdder")
                        || className.equals("java.util.concurrent.atomic.DoubleAdder")
                    )) {
                    try {
                        {
                            String[] names = new String[]{
                                    "java.time.LocalDateTime",
                                    "java.time.LocalDate",
                                    "java.time.LocalTime",
                                    "java.time.ZonedDateTime",
                                    "java.time.OffsetDateTime",
                                    "java.time.OffsetTime",
                                    "java.time.ZoneOffset",
                                    "java.time.ZoneRegion",
                                    "java.time.Period",
                                    "java.time.Duration",
                                    "java.time.Instant"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    put(Class.forName(name), writer = Jdk8DateCodec.instance);
                                    return writer;
                                }
                            }
                        }
                        {
                            String[] names = new String[]{
                                    "java.util.Optional",
                                    "java.util.OptionalDouble",
                                    "java.util.OptionalInt",
                                    "java.util.OptionalLong"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    put(Class.forName(name), writer = OptionalCodec.instance);
                                    return writer;
                                }
                            }
                        }
                        {
                            String[] names = new String[]{
                                    "java.util.concurrent.atomic.LongAdder",
                                    "java.util.concurrent.atomic.DoubleAdder"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    put(Class.forName(name), writer = AdderSerializer.instance);
                                    return writer;
                                }
                            }
                        }
                    } catch (Throwable e) {
                        // skip
                        jdk8Error = true;
                    }
                }
                
                if ((!oracleJdbcError) //
                    && className.startsWith("oracle.sql.")) {
                    try {
                        String[] names = new String[] {
                                "oracle.sql.DATE",
                                "oracle.sql.TIMESTAMP"
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = DateCodec.instance);
                                return writer;
                            }
                        }
                    } catch (Throwable e) {
                        // skip
                        oracleJdbcError = true;
                    }
                }
                
                if ((!springfoxError) //
                    && className.equals("springfox.documentation.spring.web.json.Json")) {
                    try {
                        put(Class.forName("springfox.documentation.spring.web.json.Json"), //
                                writer = SwaggerJsonSerializer.instance);
                        return writer;
                    } catch (ClassNotFoundException e) {
                        // skip
                        springfoxError = true;
                    }
                }

                if ((!guavaError) //
                        && className.startsWith("com.google.common.collect.")) {
                    try {
                        String[] names = new String[] {
                                "com.google.common.collect.HashMultimap",
                                "com.google.common.collect.LinkedListMultimap",
                                "com.google.common.collect.LinkedHashMultimap",
                                "com.google.common.collect.ArrayListMultimap",
                                "com.google.common.collect.TreeMultimap"
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = GuavaCodec.instance);
                                return writer;
                            }
                        }
                    } catch (ClassNotFoundException e) {
                        // skip
                        guavaError = true;
                    }
                }

                if ((!jsonnullError) && className.equals("net.sf.json.JSONNull")) {
                    try {
                        put(Class.forName("net.sf.json.JSONNull"), writer = MiscCodec.instance);
                        return writer;
                    } catch (ClassNotFoundException e) {
                        // skip
                        jsonnullError = true;
                    }
                }
                
				if (!jsonobjectError && className.equals("org.json.JSONObject")) {
					try {
						put(Class.forName("org.json.JSONObject"), writer = JSONObjectCodec.instance);
						return writer;
					} catch (ClassNotFoundException e) {
						// skip
						jsonobjectError = true;
					}
				}

                if ((!jodaError) && className.startsWith("org.joda.")) {
                    try {
                        String[] names = new String[] {
                                "org.joda.time.LocalDate",
                                "org.joda.time.LocalDateTime",
                                "org.joda.time.LocalTime",
                                "org.joda.time.Instant",
                                "org.joda.time.DateTime",
                                "org.joda.time.Period",
                                "org.joda.time.Duration",
                                "org.joda.time.DateTimeZone",
                                "org.joda.time.UTCDateTimeZone",
                                "org.joda.time.tz.CachedDateTimeZone",
                                "org.joda.time.tz.FixedDateTimeZone",
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                put(Class.forName(name), writer = JodaCodec.instance);
                                return writer;
                            }
                        }
                    } catch (ClassNotFoundException e) {
                        // skip
                        jodaError = true;
                    }
                }

                if ("java.nio.HeapByteBuffer".equals(className)) {
                    put(clazz, writer = ByteBufferCodec.instance);
                    return writer;
                }

                if ("org.javamoney.moneta.Money".equals(className)) {
                    put(clazz, writer = MonetaCodec.instance);
                    return writer;
                }

                Class[] interfaces = clazz.getInterfaces();
                if (interfaces.length == 1 && interfaces[0].isAnnotation()) {
                    put(clazz, AnnotationSerializer.instance);
                    return AnnotationSerializer.instance;
                }

                if (TypeUtils.isProxy(clazz)) {
                    //如果是CGLIB或javassist生成的代理类,就放父类的序列化器
                    Class<?> superClazz = clazz.getSuperclass();

                    ObjectSerializer superWriter = getObjectWriter(superClazz);
                    put(clazz, superWriter);
                    return superWriter;
                }
                //不管是不是动态代理类型,都是用JavaBean序列化器
                if (Proxy.isProxyClass(clazz)) {
                    Class handlerClass = null;

                    if (interfaces.length == 2) {
                        handlerClass = interfaces[1];
                    } else {
                        for (Class proxiedInterface : interfaces) {
                            if (proxiedInterface.getName().startsWith("org.springframework.aop.")) {
                                continue;
                            }
                            if (handlerClass != null) {
                                handlerClass = null; // multi-matched
                                break;
                            }
                            handlerClass = proxiedInterface;
                        }
                    }

                    if (handlerClass != null) {
                        ObjectSerializer superWriter = getObjectWriter(handlerClass);
                        put(clazz, superWriter);
                        return superWriter;
                    }
                }

                if (create) {
                    writer = createJavaBeanSerializer(clazz);
                    put(clazz, writer);
                }
            }

            if (writer == null) {
                //上面向config中添加了类对应的序列化器,现在获取Writer返回
                writer = get(clazz);
            }
        }
        return writer;
    }

总结 整个解析过程,相对来说,比较地简单。因为,这个解析工作从原理上来讲,也并不复杂。困难地在于,如何处理不同的数据类型,以及在处理过程中如何保证处理的效率。这即是fastjson之所以产生的原因。 其它 具体的序列化各个函数 blog.csdn.net/weixin_4156…

公众号

博客地址 blog.csdn.net/weixin_4156…

公众号

请关注 程序员面试之道

mp.weixin.qq.com/s/U2KvuYsRq…