[关闭]
@Yano 2017-08-10T15:21:37.000000Z 字数 8112 阅读 2691

FastJSON 源码分析

Java


Git 链接

Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。

git:https://github.com/alibaba/fastjson

Samples:https://github.com/alibaba/fastjson/wiki/Samples-DataBind

测试代码

  1. @Test
  2. public void test() {
  3. User user = new User(0L, "json");
  4. String jsonString = JSON.toJSONString(user);
  5. System.out.println(jsonString);
  6. User parseUser = JSON.parseObject(jsonString, User.class);
  7. System.out.println(parseUser);
  8. }
  1. public class User {
  2. private Long id;
  3. private String name;
  4. public User(long id, String name) {
  5. this.id = id;
  6. this.name = name;
  7. }
  8. public Long getId() {
  9. return id;
  10. }
  11. public void setId(Long id) {
  12. this.id = id;
  13. }
  14. public String getName() {
  15. return name;
  16. }
  17. public void setName(String name) {
  18. this.name = name;
  19. }
  20. @Override
  21. public String toString() {
  22. return "User [id=" + id + ", name=" + name + "]";
  23. }
  24. }

输出:

{"id":0,"name":"json"}
User [id=0, name=json]

序列化、反序列化流程

序列化流程

根据对象的实例,获取对象的类,判断出实现 ObjectSerializer 接口的类,调用接口的方法 write,将对象实例转化成 String。

反序列化流程

根据输入的 Class clazz,判断出实现 ObjectDeserializer 的类,调用接口的方法 deserialze,将 String 转化成对象实例。

序列化源码分析

最终会调用到函数:

  1. public static String toJSONString(Object object, //
  2. SerializeConfig config, //
  3. SerializeFilter[] filters, //
  4. String dateFormat, //
  5. int defaultFeatures, //
  6. SerializerFeature... features) {
  7. // out 对象保存解析对象的结果,最终会转换成 string(return out.toString();)
  8. SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);
  9. try {
  10. // 解析对象的类
  11. JSONSerializer serializer = new JSONSerializer(out, config);
  12. if (dateFormat != null && dateFormat.length() != 0) {
  13. serializer.setDateFormat(dateFormat);
  14. serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
  15. }
  16. if (filters != null) {
  17. for (SerializeFilter filter : filters) {
  18. serializer.addFilter(filter);
  19. }
  20. }
  21. // 将对象 object 解析成 string,保存在内部的 out 中
  22. serializer.write(object);
  23. return out.toString();
  24. } finally {
  25. out.close();
  26. }
  27. }

其中 write 方法如下:

  1. public final void write(Object object) {
  2. if (object == null) {
  3. out.writeNull();
  4. return;
  5. }
  6. Class<?> clazz = object.getClass();
  7. /**
  8. * 获取到对应的解析类,所有的类都实现了接口 ObjectSerializer
  9. *
  10. * 如果是 bool,会定位到 BooleanCodec 类
  11. * 如果是 bool[],会定位到 PrimitiveArraySerializer 类
  12. */
  13. ObjectSerializer writer = getObjectWriter(clazz);
  14. try {
  15. // 调用 write 方法,把对应的域,写入 out 对象中!
  16. writer.write(this, object, null, null, 0);
  17. } catch (IOException e) {
  18. throw new JSONException(e.getMessage(), e);
  19. }
  20. }

在测试用例中,使用的是类 JavaBeanSerializer,因为要序列化的是自定义的 JavaBean 类 User。

SerializeConfig

其中 put 函数是将键值对放入 IdentityHashMap serializers 中。

  1. public SerializeConfig(int tableSize, boolean fieldBase) {
  2. this.fieldBased = fieldBase;
  3. serializers = new IdentityHashMap<Type, ObjectSerializer>(tableSize);
  4. try {
  5. if (asm) {
  6. asmFactory = new ASMSerializerFactory();
  7. }
  8. } catch (Throwable eror) {
  9. asm = false;
  10. }
  11. put(Boolean.class, BooleanCodec.instance);
  12. put(Character.class, CharacterCodec.instance);
  13. put(Byte.class, IntegerCodec.instance);
  14. put(Short.class, IntegerCodec.instance);
  15. put(Integer.class, IntegerCodec.instance);
  16. put(Long.class, LongCodec.instance);
  17. put(Float.class, FloatCodec.instance);
  18. put(Double.class, DoubleSerializer.instance);
  19. put(BigDecimal.class, BigDecimalCodec.instance);
  20. put(BigInteger.class, BigIntegerCodec.instance);
  21. put(String.class, StringCodec.instance);
  22. put(byte[].class, PrimitiveArraySerializer.instance);
  23. put(short[].class, PrimitiveArraySerializer.instance);
  24. put(int[].class, PrimitiveArraySerializer.instance);
  25. put(long[].class, PrimitiveArraySerializer.instance);
  26. put(float[].class, PrimitiveArraySerializer.instance);
  27. put(double[].class, PrimitiveArraySerializer.instance);
  28. put(boolean[].class, PrimitiveArraySerializer.instance);
  29. put(char[].class, PrimitiveArraySerializer.instance);
  30. put(Object[].class, ObjectArrayCodec.instance);
  31. put(Class.class, MiscCodec.instance);
  32. // 省略……
  33. put(LinkedList.class, CollectionCodec.instance);
  34. }

分析其中的代码:

put(Boolean.class, BooleanCodec.instance);

类 BooleanCodec 继承了接口 ObjectSerializer, ObjectDeserializer,两个接口:

  1. public interface ObjectSerializer {
  2. /**
  3. * fastjson invokes this call-back method during serialization when it encounters a field of the
  4. * specified type.
  5. * @param serializer
  6. * @param object src the object that needs to be converted to Json.
  7. * @param fieldName parent object field name
  8. * @param fieldType parent object field type
  9. * @param features parent object field serializer features
  10. * @throws IOException
  11. */
  12. void write(JSONSerializer serializer, //
  13. Object object, //
  14. Object fieldName, //
  15. Type fieldType, //
  16. int features) throws IOException;
  17. }
  1. public interface ObjectDeserializer {
  2. /**
  3. * fastjson invokes this call-back method during deserialization when it encounters a field of the
  4. * specified type.
  5. * <p>In the implementation of this call-back method, you should consider invoking
  6. * {@link JSON#parseObject(String, Type, Feature[])} method to create objects
  7. * for any non-trivial field of the returned object.
  8. *
  9. * @param parser context DefaultJSONParser being deserialized
  10. * @param type The type of the Object to deserialize to
  11. * @param fieldName parent object field name
  12. * @return a deserialized object of the specified type which is a subclass of {@code T}
  13. */
  14. <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName);
  15. int getFastMatchToken();
  16. }

BooleanCodec 的 write 实现如下,其中参数 serializer 中包含实例为 out 的 SerializeWriter 对象,out 最终转换成输出的 string;

  1. public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
  2. SerializeWriter out = serializer.out;
  3. Boolean value = (Boolean) object;
  4. if (value == null) {
  5. out.writeNull(SerializerFeature.WriteNullBooleanAsFalse);
  6. return;
  7. }
  8. if (value.booleanValue()) {
  9. out.write("true");
  10. } else {
  11. out.write("false");
  12. }
  13. }

BooleanCodec 的 deserialze 实现如下,如果 lexer.token() 是 true、1等,就会返回true;类 JSONToken 中有对各种字符的定义。

  1. @SuppressWarnings("unchecked")
  2. public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
  3. final JSONLexer lexer = parser.lexer;
  4. Boolean boolObj;
  5. try {
  6. if (lexer.token() == JSONToken.TRUE) {
  7. lexer.nextToken(JSONToken.COMMA);
  8. boolObj = Boolean.TRUE;
  9. } else if (lexer.token() == JSONToken.FALSE) {
  10. lexer.nextToken(JSONToken.COMMA);
  11. boolObj = Boolean.FALSE;
  12. } else if (lexer.token() == JSONToken.LITERAL_INT) {
  13. int intValue = lexer.intValue();
  14. lexer.nextToken(JSONToken.COMMA);
  15. if (intValue == 1) {
  16. boolObj = Boolean.TRUE;
  17. } else {
  18. boolObj = Boolean.FALSE;
  19. }
  20. } else {
  21. Object value = parser.parse();
  22. if (value == null) {
  23. return null;
  24. }
  25. boolObj = TypeUtils.castToBoolean(value);
  26. }
  27. } catch (Exception ex) {
  28. throw new JSONException("parseBoolean error, field : " + fieldName, ex);
  29. }
  30. if (clazz == AtomicBoolean.class) {
  31. return (T) new AtomicBoolean(boolObj.booleanValue());
  32. }
  33. return (T) boolObj;
  34. }

反序列化

在反序列化string到对象时,会调用下面的函数。其中最重要的是第25行代码,将输入的input字符串转换成对应的class类型。

  1. @SuppressWarnings("unchecked")
  2. public static <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor,
  3. int featureValues, Feature... features) {
  4. if (input == null) {
  5. return null;
  6. }
  7. if (features != null) {
  8. for (Feature feature : features) {
  9. featureValues |= feature.mask;
  10. }
  11. }
  12. DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);
  13. if (processor != null) {
  14. if (processor instanceof ExtraTypeProvider) {
  15. parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);
  16. }
  17. if (processor instanceof ExtraProcessor) {
  18. parser.getExtraProcessors().add((ExtraProcessor) processor);
  19. }
  20. if (processor instanceof FieldTypeResolver) {
  21. parser.setFieldTypeResolver((FieldTypeResolver) processor);
  22. }
  23. }
  24. // 获取所需要的类
  25. T value = (T) parser.parseObject(clazz, null);
  26. parser.handleResovleTask(value);
  27. parser.close();
  28. return (T) value;
  29. }

T value = (T) parser.parseObject(clazz, null) 的代码如下,对于本例中的 User 对象,最终ObjectDeserializer会定位到类JavaBeanDeserializer,其 deserialze 代码有点长,就不贴出来了。

  1. @SuppressWarnings("unchecked")
  2. public <T> T parseObject(Type type, Object fieldName) {
  3. int token = lexer.token();
  4. if (token == JSONToken.NULL) {
  5. lexer.nextToken();
  6. return null;
  7. }
  8. if (token == JSONToken.LITERAL_STRING) {
  9. if (type == byte[].class) {
  10. byte[] bytes = lexer.bytesValue();
  11. lexer.nextToken();
  12. return (T) bytes;
  13. }
  14. if (type == char[].class) {
  15. String strVal = lexer.stringVal();
  16. lexer.nextToken();
  17. return (T) strVal.toCharArray();
  18. }
  19. }
  20. // 根据输入的class类型,获取解析所需要的类
  21. ObjectDeserializer derializer = config.getDeserializer(type);
  22. try {
  23. return (T) derializer.deserialze(this, type, fieldName);
  24. } catch (JSONException e) {
  25. throw e;
  26. } catch (Throwable e) {
  27. throw new JSONException(e.getMessage(), e);
  28. }
  29. }

其它用法

可以利用fastjson,将"1 2 3 4 5" 或 "1,2,3,4,5"这样的字符串,转换成数组。实际应用过程中,十分方便简洁。

  1. @Test
  2. public void testArray() {
  3. String arrayString = "1 2 3 4 5";
  4. int[] array1 = JSON.parseObject("[" + arrayString + "]", int[].class);
  5. System.out.println(Arrays.toString(array1));
  6. String boolString = "1, true, 0, false";
  7. boolean[] array2 = JSON.parseObject("[" + boolString + "]", boolean[].class);
  8. System.out.println(Arrays.toString(array2));
  9. }

fastjson 的整理思路

总的来说,是定义了两个接口:ObjectSerializer 和 ObjectDeserializer 。针对不同的类,实现了不同的序列化和反序列化方式,并能够根据类的信息,选择合适的接口实现类。

总结

仅仅通过序列化、反序列化一个Java Bean对象,对fastjson的源码进行分析。很多地方没有展开讨论,至少没法通过博客的形式写出来,具体细节太多了。如果有什么问题,欢迎指正~

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注