FastJSON|FastJSON 源码分析

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
测试代码

@Test public void test() { User user = new User(0L, "json"); String jsonString = JSON.toJSONString(user); System.out.println(jsonString); User parseUser = JSON.parseObject(jsonString, User.class); System.out.println(parseUser); }

public class User { private Longid; private String name; public User(long id, String name) { this.id = id; this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }@Override public String toString() { return "User [id=" + id + ", name=" + name + "]"; } }

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

序列化、反序列化流程 序列化流程 根据对象的实例,获取对象的类,判断出实现 ObjectSerializer 接口的类,调用接口的方法 write,将对象实例转化成 String。
反序列化流程 根据输入的 Class clazz,判断出实现 ObjectDeserializer 的类,调用接口的方法 deserialze,将 String 转化成对象实例。
序列化源码分析 最终会调用到函数:
public static String toJSONString(Object object, // SerializeConfig config, // SerializeFilter[] filters, // String dateFormat, // int defaultFeatures, // SerializerFeature... features) { // out 对象保存解析对象的结果,最终会转换成 string(return out.toString(); ) SerializeWriter out = new SerializeWriter(null, defaultFeatures, features); try { // 解析对象的类 JSONSerializer serializer = new JSONSerializer(out, config); if (dateFormat != null && dateFormat.length() != 0) { serializer.setDateFormat(dateFormat); serializer.config(SerializerFeature.WriteDateUseDateFormat, true); } if (filters != null) { for (SerializeFilter filter : filters) { serializer.addFilter(filter); } } // 将对象 object 解析成 string,保存在内部的 out 中 serializer.write(object); return out.toString(); } finally { out.close(); } }

其中 write 方法如下:
public final void write(Object object) { if (object == null) { out.writeNull(); return; } Class clazz = object.getClass(); /** * 获取到对应的解析类,所有的类都实现了接口 ObjectSerializer * * 如果是 bool,会定位到 BooleanCodec 类 * 如果是 bool[],会定位到 PrimitiveArraySerializer 类 */ ObjectSerializer writer = getObjectWriter(clazz); try { // 调用 write 方法,把对应的域,写入 out 对象中! writer.write(this, object, null, null, 0); } catch (IOException e) { throw new JSONException(e.getMessage(), e); } }

在测试用例中,使用的是类 JavaBeanSerializer,因为要序列化的是自定义的 JavaBean 类 User。
SerializeConfig
其中 put 函数是将键值对放入 IdentityHashMap serializers 中。
public SerializeConfig(int tableSize, boolean fieldBase) { this.fieldBased = fieldBase; serializers = new IdentityHashMap(tableSize); try { if (asm) { asmFactory = new ASMSerializerFactory(); } } catch (Throwable eror) { asm = false; } 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, PrimitiveArraySerializer.instance); put(short[].class, PrimitiveArraySerializer.instance); put(int[].class, PrimitiveArraySerializer.instance); put(long[].class, PrimitiveArraySerializer.instance); put(float[].class, PrimitiveArraySerializer.instance); put(double[].class, PrimitiveArraySerializer.instance); put(boolean[].class, PrimitiveArraySerializer.instance); put(char[].class, PrimitiveArraySerializer.instance); put(Object[].class, ObjectArrayCodec.instance); put(Class.class, MiscCodec.instance); // 省略…… put(LinkedList.class, CollectionCodec.instance); }

分析其中的代码:
put(Boolean.class, BooleanCodec.instance);

类 BooleanCodec 继承了接口 ObjectSerializer, ObjectDeserializer,两个接口:
public interface ObjectSerializer {/** * fastjson invokes this call-back method during serialization when it encounters a field of the * specified type. * @param serializer * @param object src the object that needs to be converted to Json. * @param fieldName parent object field name * @param fieldType parent object field type * @param features parent object field serializer features * @throws IOException */ void write(JSONSerializer serializer, // Object object, // Object fieldName, // Type fieldType, // int features) throws IOException; }

public interface ObjectDeserializer { /** * fastjson invokes this call-back method during deserialization when it encounters a field of the * specified type. * In the implementation of this call-back method, you should consider invoking * {@link JSON#parseObject(String, Type, Feature[])} method to create objects * for any non-trivial field of the returned object. * * @param parser context DefaultJSONParser being deserialized * @param type The type of the Object to deserialize to * @param fieldName parent object field name * @return a deserialized object of the specified type which is a subclass of {@code T} */ T deserialze(DefaultJSONParser parser, Type type, Object fieldName); int getFastMatchToken(); }

BooleanCodec 的 write 实现如下,其中参数 serializer 中包含实例为 out 的 SerializeWriter 对象,out 最终转换成输出的 string;
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException { SerializeWriter out = serializer.out; Boolean value = https://www.it610.com/article/(Boolean) object; if (value == null) { out.writeNull(SerializerFeature.WriteNullBooleanAsFalse); return; } if (value.booleanValue()) { out.write("true"); } else { out.write("false"); } }

BooleanCodec 的 deserialze 实现如下,如果 lexer.token() 是 true、1等,就会返回true;类 JSONToken 中有对各种字符的定义。
@SuppressWarnings("unchecked") public T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) { final JSONLexer lexer = parser.lexer; Boolean boolObj; try { if (lexer.token() == JSONToken.TRUE) { lexer.nextToken(JSONToken.COMMA); boolObj = Boolean.TRUE; } else if (lexer.token() == JSONToken.FALSE) { lexer.nextToken(JSONToken.COMMA); boolObj = Boolean.FALSE; } else if (lexer.token() == JSONToken.LITERAL_INT) { int intValue = https://www.it610.com/article/lexer.intValue(); lexer.nextToken(JSONToken.COMMA); if (intValue == 1) { boolObj = Boolean.TRUE; } else { boolObj = Boolean.FALSE; } } else { Object value = parser.parse(); if (value == null) { return null; } boolObj = TypeUtils.castToBoolean(value); } } catch (Exception ex) { throw new JSONException("parseBoolean error, field : " + fieldName, ex); } if (clazz == AtomicBoolean.class) { return (T) new AtomicBoolean(boolObj.booleanValue()); } return (T) boolObj; }

反序列化 在反序列化string到对象时,会调用下面的函数。其中最重要的是第25行代码,将输入的input字符串转换成对应的class类型。
@SuppressWarnings("unchecked") public static T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor, int featureValues, Feature... features) { if (input == null) { return null; } if (features != null) { for (Feature feature : features) { featureValues |= feature.mask; } } DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues); if (processor != null) { if (processor instanceof ExtraTypeProvider) { parser.getExtraTypeProviders().add((ExtraTypeProvider) processor); } if (processor instanceof ExtraProcessor) { parser.getExtraProcessors().add((ExtraProcessor) processor); } if (processor instanceof FieldTypeResolver) { parser.setFieldTypeResolver((FieldTypeResolver) processor); } } // 获取所需要的类 T value = https://www.it610.com/article/(T) parser.parseObject(clazz, null); parser.handleResovleTask(value); parser.close(); return (T) value; }

T value = https://www.it610.com/article/(T) parser.parseObject(clazz, null) 的代码如下,对于本例中的 User 对象,最终ObjectDeserializer会定位到类JavaBeanDeserializer,其 deserialze 代码有点长,就不贴出来了。
@SuppressWarnings("unchecked") public T parseObject(Type type, Object fieldName) { int token = lexer.token(); if (token == JSONToken.NULL) { lexer.nextToken(); return null; } if (token == JSONToken.LITERAL_STRING) { if (type == byte[].class) { byte[] bytes = lexer.bytesValue(); lexer.nextToken(); return (T) bytes; } if (type == char[].class) { String strVal = lexer.stringVal(); lexer.nextToken(); return (T) strVal.toCharArray(); } } // 根据输入的class类型,获取解析所需要的类 ObjectDeserializer derializer = config.getDeserializer(type); try { return (T) derializer.deserialze(this, type, fieldName); } catch (JSONException e) { throw e; } catch (Throwable e) { throw new JSONException(e.getMessage(), e); } }

其它用法 可以利用fastjson,将"1 2 3 4 5" 或 "1,2,3,4,5"这样的字符串,转换成数组。实际应用过程中,十分方便简洁。
@Test public void testArray() { String arrayString = "1 2 3 4 5"; int[] array1 = JSON.parseObject("[" + arrayString + "]", int[].class); System.out.println(Arrays.toString(array1)); String boolString = "1, true, 0, false"; boolean[] array2 = JSON.parseObject("[" + boolString + "]", boolean[].class); System.out.println(Arrays.toString(array2)); }

fastjson 的整理思路 总的来说,是定义了两个接口:ObjectSerializer 和 ObjectDeserializer 。针对不同的类,实现了不同的序列化和反序列化方式,并能够根据类的信息,选择合适的接口实现类。
总结 【FastJSON|FastJSON 源码分析】仅仅通过序列化、反序列化一个Java Bean对象,对fastjson的源码进行分析。很多地方没有展开讨论,至少没法通过博客的形式写出来,具体细节太多了。如果有什么问题,欢迎指正~

    推荐阅读