`

alibaba fastjson(json序列化器)序列化部分源码解析

阅读更多

本文copy自http://www.flydmeng.com/index.php/code/alibaba-fastjson-json-serializer-chapter-source-analyse-one-global-analyse.html

 

 

fastjson官方地址: http://code.alibabatech.com/wiki/display/FastJSON/Home
    从javaeye上看到了阿里一位人士写的fastjson,特别是其中如何将java对象序列化成json字符串这段。笔者比较关注,因为在笔者的项目中就用了一个json序列化器(造的轮子)。就下载下来看了一看,先不说和笔者所用的轮子有何区别,单就用了一个简单的测试器,来测试一下两者的处理速度。测试代码就不贴了,简单地说下测试结果。在jvm充分优化的情况下(for循环执行了很多次之后),笔者所使用的java序列化器处理速度不是很均匀,在结尾有短暂的变化(可能与虚拟机回收有关系);而fastjson在后面的处理过程当中,一般很均匀(后来发现与使用的buf分配方式有关)。最主要的区别莫在于,fastjson的速度那是不能对比了。
    经过分析源码之后,发现fastjson在处理json优化上面还是下了很大的工夫的。笔者准备从以下几个方面对fastjson作一个简单的解析,也让使用fastjson的同学对fastjson有一个简单的认识。
        1    总体分析    分析json序列化的总体思路和解析过程
        2    性能分析A  针对字符生产部分(即outWriter)对不同类型数据的处理和与性能相关处理部分
        3    性别分析B  针对序列化过程部分(即objectSerializer)对不同类型的序列化过程处理和与性能相关处理部分
        4    对象解析分析    对javaBean解析部分和针对字段输出部分的处理和解析
    源码分析基于1.0.5版本。

    总体分析,首先上图,即fastjson的总体处理思想,其实也是所有json序列化器需要考虑的问题。

 

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

 

    代码分析部分

    首先,将一个对象序列化json字符串调用的是JSON对象的toJSONString方法,这里调用的是无参数方法。(注:本文不分析采用vistor实现json序列化代码的部分)。具体代码如下所示:

第一行,新产生的一个数据保存器,储存在序列化过程中产生的数据;第二行,产生统一的json序列化器,其中使用了outWriter,此类即json序列化的统一处理器;第三行,调用序列化方法开始序列化对象,以产生json字符串信息;第四行,返回已经储存的json信息。

 

Java代码  收藏代码
  1. SerializeWriter out = new SerializeWriter();  
  2.        JSONSerializer serializer = new JSONSerializer(out);  
  3.        serializer.write(object);  
  4.        return out.toString();  
 

 

 

    数据保存器(序列化输出容器)
   
    SerializeWriter是一个用于储存在序列化过程中产生的数据信息,它与jdk中的StringBuiler有着类似的功能,即将不同的数据填充到此容器中。之所以不使用StringBuilder的原因之一在于StringBuilder没有提供一些特别为性能优化的方法,并且StringBuilder在处理过程中增加了多余的操作(如新分配对象)。该容器的主要功能就是接收不同的数据,并将这些数据存储到该内部的一个字符数组当中,同时记录字符总数。
    既然充当了一个数据输出的角色,那么就可以往其中输入任何的数据,包括int,byte,short等基本类型和对应的包装类型,也包括日期数据,以及经常使用的字符串数据等。对于在这些数据类型之外的其它类型,由于json的特殊结构,所有的高级类型均可以转化于这些基础类型的组织体,所以不需要再针对高级类型作处理了(这些是序列化器应该考虑的问题)。

    首先对SerializeWriter的方法(输出和追加)作一个预览:

方法总共可以分五个部分,第一个部分是针对writer基本功能一个扩展,即支持输出int,字符,以及字符数组,追加字符数组(包括字符串)等;第二个部分提供了写整形和长整形的基本方法;第三个部分是提供写基本数据类型数组的支持;第四个部分是提供写一个数字+一个字符的形式,比如数据+[,\],}]这种格式;第五个部分是提供写数据串,主是是针对字符串追加双引号或单引号(以支持标准json)。

 

Java代码  收藏代码
  1. public void write(int c)  
  2. public void write(char c)  
  3. public void write(char c[], int off, int len)  
  4. public void write(String str, int off, int len)  
  5. public SerializeWriter append(CharSequence csq)  
  6. public SerializeWriter append(CharSequence csq, int start, int end)  
  7. public SerializeWriter append(char c)  
  8.    
  9. public void writeInt(int i)  
  10. public void writeLong(long i)  
  11.    
  12. public void writeBooleanArray(boolean[] array)  
  13. public void writeShortArray(short[] array)  
  14. public void writeByteArray(byte[] array)  
  15. public void writeIntArray(int[] array)  
  16. public void writeIntArray(Integer[] array)  
  17. public void writeLongArray(long[] array)  
  18.    
  19. public void writeIntAndChar(int i, char c)  
  20. public void writeLongAndChar(long i, char c)  
  21.    
  22. public void writeStringWithDoubleQuote(String text)  
  23. public void writeKeyWithDoubleQuote(String text)  
  24. public void writeStringWithSingleQuote(String text)  
  25. public void writeStringArray(String[] array)  
  26. public void writeKeyWithSingleQuote(String text)  
  27. public void writeKeyWithDoubleQuoteIfHashSpecial(String text)  
  28. public void writeKeyWithSingleQuoteIfHashSpecial(String text)  
 

 

    五个部分的方法,每个部分都有其特殊的作用和意义,针对最常用的数字和字符串作了特别的对待。

    在实现上面,SerializeWriter使用了一个内部的字符数组作为数据的储存器,同时使用了一个计数器计算当前存储的字符量。既然使用了字符数组,那么肯定有相关的操作,如字符扩容等。整个写数据的过程,其实就是往这个字符数组追加数据的过程,需要考虑只是如何追加数据的问题,即上面所列出的这么多些方法。在最终写完数据之后,即可将这个字符数组转为我们所需要的字符串了。

    对象序列化入口

    JsonSerializer,准备地讲,这个类不应该叫这个名字,因为它与其它的对象序列化器相混淆了。这只是一个提供对象序列化的一个入口;同时,它持有所有具体负责对象序列化工作类的引用。将这些序列化器集中起来,需要用到哪个对象序列化器时,就取出这个序列化器,并调用相应的序列化方法。
    既然是对象序列化入口,它就需要关注两个事情。一是我们究竟有哪些序列化器可以使用,二是对于一个对象,应该使用哪一个序列化器来进行工作。对于这两个问题,JsonSerializer内部持有一个JSONSerializerMap的属性,即表示应该序列化的对象类型和对应的序列化器的一个映射。我们来看默认的构造方法,它使用了默认的全局对象类型和对象序列化器映射:

 

Java代码  收藏代码
  1. public JSONSerializer(SerializeWriter out){  
  2.         this(out, JSONSerializerMap.getGlobalInstance());  
  3.     }  
 

 

这时使用了全局的一个对象序列化器映射,加上后面在getObjectWriter中追加的对象序列化器映射。在整个jsonSerializer中,可以使用的对象序列化器有以下这些:

 

 

 

 

Java代码  收藏代码
  1. put(Boolean.class, BooleanSerializer.instance);  
  2.         put(Byte.class, ByteSerializer.instance);  
  3.         put(Short.class, ShortSerializer.instance);  
  4.         put(Integer.class, IntegerSerializer.instance);  
  5.         put(Long.class, LongSerializer.instance);  
  6.         put(Float.class, FloatSerializer.instance);  
  7.         put(Double.class, DoubleSerializer.instance);  
  8.         put(BigDecimal.class, BigDecimalSerializer.instance);  
  9.         put(BigInteger.class, BigIntegerSerializer.instance);  
  10.         put(String.class, StringSerializer.instance);  
  11.         put(byte[].class, ByteArraySerializer.instance);  
  12.         put(short[].class, ShortArraySerializer.instance);  
  13.         put(int[].class, IntArraySerializer.instance);  
  14.         put(long[].class, LongArraySerializer.instance);  
  15.         put(float[].class, FloatArraySerializer.instance);  
  16.         put(double[].class, DoubleArraySerializer.instance);  
  17.         put(boolean[].class, BooleanArraySerializer.instance);  
  18.         put(Integer[].class, IntegerArraySerializer.instance);  
  19.         put(String[].class, StringArraySerializer.instance);  
  20.         put(Object[].class, ObjectArraySerializer.instance);  
  21.         put(Class.class, ClassSerializer.instance);  
  22.    
  23.         // atomic  
  24.         put(AtomicBoolean.class, AtomicBooleanSerializer.instance);  
  25.         put(AtomicInteger.class, AtomicIntegerSerializer.instance);  
  26.         put(AtomicLong.class, AtomicLongSerializer.instance);  
  27.         put(AtomicReference.class, AtomicReferenceSerializer.instance);  
  28.         put(AtomicIntegerArray.class, AtomicIntegerArraySerializer.instance);  
  29.         put(AtomicLongArray.class, AtomicLongArraySerializer.instance);  
  30.    
  31.         // jmx  
  32.         put(CompositeData.class, CompositeDataSerializer.instance);  
  33.         put(CompositeDataSupport.class, CompositeDataSerializer.instance);  
  34.         put(TabularData.class, TabularDataSerializer.instance);  
  35.         put(TabularDataSupport.class, TabularDataSerializer.instance);  
  36.         put(ObjectName.class, ObjectNameSerializer.instance);  
  37.         put(SimpleType.class, SimpleTypeSerializer.instance);  
  38.    
  39.         //在执行过程中追加部分  
  40.                 mapping.put(clazz, MapSerializer.instance);  
  41.                 mapping.put(clazz, ListSerializer.instance);  
  42.                 mapping.put(clazz, CollectionSerializer.instance);  
  43.                 mapping.put(clazz, DateSerializer.instance);  
  44.                 mapping.put(clazz, JSONAwareSerializer.instance);  
  45.                 mapping.put(clazz, JSONStreamAwareSerializer.instance);  
  46.                 mapping.put(clazz, EnumSerializer.instance);  
  47.                 mapping.put(clazz, new ArraySerializer(compObjectSerializer));  
  48.                 mapping.put(clazz, new ExceptionSerializer(clazz));  
  49.                 mapping.put(clazz, new JavaBeanSerializer(clazz));  

 

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

 

Java代码  收藏代码
  1. Class<?> clazz = object.getClass();  
  2.             ObjectSerializer writer = getObjectWriter(clazz);  
  3.             writer.write(this, object);  

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

 

 

    序列化过程

    正如上面所说,进入序列化工作之后,即是针对每一种类型进行序列化处理了。该序列化工作使用了统一的方法,即实现了统一的序列化方法:

 

Java代码  收藏代码
  1. void write(JSONSerializer serializer, Object object) throws IOException  

 

 

 

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

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

 

 

 


 

 

Java代码  收藏代码
  1. SerializeWriter out = serializer.getWrier();  
  2.         Integer value = (Integer) object;  
  3.         out.writeInt(value.intValue());  

 

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

 

总结

    整个解析过程,相对来说,比较地简单。因为,这个解析工作从原理上来讲,也并不复杂。困难地在于,如何处理不同的数据类型,以及在处理过程中如何保证处理的效率。这即是fastjson之所以产生的原因。
    本篇从整个结构出发,对fastjson中的json序列化过程有了一个初步的理解,让大家都能够很好地正解fastjson,包括fastjson本身在实现上可能存在的不合理情况。在下一篇中,就效率实现上的两个重要方面(输出效率和解析过程)分别进行解析。

分享到:
评论

相关推荐

    com.alibaba.fastjson json解析工具包

    `com.alibaba.fastjson`是阿里巴巴开发的一个高性能的Java JSON库,被广泛应用于各种JSON处理场景,如数据序列化、反序列化、JSON字符串解析等。它以其高效、易用和全面的功能,深受Java开发者喜爱。本篇文章将深入...

    Alibaba Fastjson Jar包.zip

    3. 功能全面:除了基础的解析和序列化,Fastjson还支持JSONPath(类似CSS选择器的JSON查询方式)、JSON Schema验证、日期格式化、自定义类型转换等高级特性。 4. 支持Java集合和JavaBean:Fastjson可以直接将JSON...

    fastjson解析json的jar

    2. **反序列化**:将JSON字符串解析为Java对象。Fastjson提供了`JSON.parseObject(jsonStr, YourClass.class)`方法,能够将JSON字符串转化为指定类型的Java对象。 3. **映射机制**:Fastjson支持字段映射,即使JSON...

    封装 fastjson 的json格式化工具

    它具有性能优异、使用简单等优点,广泛应用于Java Web开发中,特别是对于数据的序列化与反序列化操作。在实际开发中,我们经常需要将JSON字符串进行格式化,以便于查看和调试,本文将详细介绍如何使用Fastjson封装一...

    com.alibaba.fastjson.JSON , net.sf.json.JSONObject

    Fastjson支持Java对象与JSON之间的相互转换,包括JSON字符串到Java对象的反序列化以及Java对象到JSON字符串的序列化。它还提供了解析JSON和生成JSON的功能,可以方便地进行JSON操作,例如: 1. 将Java对象转换为...

    S14-fastjson反序列化1

    总之,理解 Fastjson 的序列化和反序列化机制,以及如何使用 `JSON.parseObject` 和 `JSON.parse` 方法,对于编写涉及 JSON 数据交换的 Java 代码至关重要。同时,确保安全使用这些功能以避免潜在的安全风险也是...

    SpringBoot Redis配置Fastjson进行序列化和反序列化实现

    这里,我们为`value`和`hashValue`设置了Fastjson序列化器,而`key`和`hashKey`使用了默认的`StringRedisSerializer`,因为Redis的key通常为字符串。 **3. 示例实体类** 为了演示序列化和反序列化的效果,我们可以...

    springmvc fastjson 反序列化时间格式化方法(推荐)

    在Spring MVC中,Fastjson是一个常用的JSON库,用于序列化和反序列化Java对象。当我们在处理日期时间字段时,可能会遇到反序列化时日期格式不一致的问题,导致默认显示为时间戳。本文将详细介绍两种解决Spring MVC中...

    fastjson的jar包(alibaba.fastson引用所需jar包).rar

    此外,Fastjson还提供了强大的序列化和反序列化功能,可以自动处理Java Bean的属性,包括处理transient关键字、忽略null值、处理枚举类型等。这极大地简化了开发者的工作,使得他们在处理JSON数据时无需编写过多的...

    JSON序列化及反序列化工具

    10万次序列化,1万次反序列化,毫秒。 阿里序列化时间 1122 1054 1115 阿里反序列化时间 409 423 412 HZS序列化时间 884 864 880 HZS反序列化时间 392 375 394 JAVA7版已经逼近阿里的速度,JAVA8版利用了闭包技术...

    com.alibaba.fastjson.JSONObject.rar

    除了这些基本操作,JSONObject还支持遍历、序列化、反序列化等功能,使得在Java应用中处理JSON数据变得极其便捷。例如,`toJavaObject(Class&lt;T&gt; clazz)`方法可以将JSONObject转换为指定类型的Java对象,这在处理复杂...

    Json_Gson_FastJson解析

    反序列化JSON回Java对象: ```java Person deserializedPerson = gson.fromJson(jsonString, Person.class); ``` 3. **阿里巴巴FastJson**: FastJson是阿里巴巴开发的高性能的JSON库,它的性能在很多测试...

    阿里巴巴json解析 fastjson.jar

    1. JSON序列化:Fastjson可以将Java对象转化为JSON字符串,这个过程被称为序列化。例如,一个Java对象可以通过`JSON.toJSONString(obj)`方法快速转换成JSON字符串。 2. JSON反序列化:反之,Fastjson也能将JSON字符...

    最新fastJSON C#的JSON开发包 v2.1.18

    FastJSON 是一个高效的 JSON 序列化和反序列化库,尤其在C#开发环境中被广泛应用。它以其轻量级、快速和简单的特点,使得处理JSON数据变得极其便捷。在这个最新的版本 v2.1.18 中,FastJSON 提供了更多的优化和改进...

    Gson和fastJson解析json

    // 将JSON字符串反序列化回Java对象 ``` **FastJson** FastJson是阿里巴巴开发的高性能的JSON库,它的速度比Gson更快,特别适合大数据量的处理。FastJson同样提供了简单易用的API,支持JSON与Java对象的相互转换...

    SpringBoot中使用FastJson解析Json数据示例代码

    在Spring Boot应用中,FastJson是一个非常常用的JSON处理库,由阿里巴巴开发,它提供了高效的JSON序列化和反序列化功能。本示例将探讨如何在Spring Boot项目中集成并使用FastJson来解析JSON数据。 首先,我们需要在...

    Alibaba_FastJson的Jar包和工具类

    1. **JSON序列化与反序列化**:FastJson提供了简单易用的API,可以将Java对象快速转换为JSON字符串,同时也可以将JSON字符串解析为Java对象。这种转换过程非常高效,大大简化了开发过程中数据交换的复杂性。 2. **...

    fastjson1.2.24反序列化RCE

    要复现这个漏洞,我们需要创建一个恶意的JSON字符串,然后使用Fastjson的`JSON.parseObject()`或`JSON.parseArray()`方法进行反序列化。以下是一些关键步骤: 1. **构建恶意JSON数据**:创建一个包含`MethodHandle`...

    com.alibaba.fastjson.JSONArray依赖jar.rar

    在Java世界中,数据序列化与反序列化是一项重要的任务,它涉及到对象与JSON格式之间的转换。阿里巴巴的Fastjson库以其高效、易用的特点,成为了广大开发者青睐的选择。尤其在处理数组类型的JSON数据时,Fastjson中的...

    JSON序列化与反序列化JAVA工具

    10万次序列化,1万次反序列化,毫秒。 阿里序列化时间 1229 1133 1179 阿里反序列化时间 478 523 466 HZS序列化时间 1089 998 1010 HZS反序列化时间 606 623 635 测试代码如下: { org.hzs.json.JSONObject bjson...

Global site tag (gtag.js) - Google Analytics