初步研究fastjson 的 toJSONString方法及其原理

Object转JsonString

如何使用:JSON.toJSONString(obj);

处理逻辑:JSON类是一个抽象类,实现了其中一个名为JSONAware的接口,这个接口中只有一个方法就是String toJSONString(),如下图所示:

初步研究fastjson 的 toJSONString方法及其原理_第1张图片 

 该方法的实现逻辑是:

    public String toJSONString() {
        SerializeWriter out = new SerializeWriter();
        try {
            new JSONSerializer(out).write(this);
            return out.toString();
        } finally {
            out.close();
        }
    }

SerializeWriter是Writer的子类,Writer是io包中的一个写字符流的抽象类,暂且不管。

new JSONSerializer,这里new的是一个

    public JSONSerializer(SerializeWriter out){
        this(out, SerializeConfig.getGlobalInstance());
    }
    public JSONSerializer(SerializeWriter out, SerializeConfig config){
        this.out = out;
        this.config = config;
    }

 接下来就要开始执行write操作,代码如下图所示,这里的object就是我们输入的待转变的内容,它可能是一个VO,是一个List,或者是个Map。

首先进行判空操作,

其次获取object的对象类型clazz,通过getObjectWriter工厂方法获取对应的(ObjectSerializer)writer,内部实现类似于HashMap的get,事实上类型和writer的映射关系存储在IdentityHashMap类中,详情自行查看SerializeConfig的SerializeConfig(int tableSize, boolean fieldBase)方法。例如List的ObjectSerializer是ListSerializer

接下来执行获取的具体对象类型的(ObjectSerializer)writer的write方法。

public final SerializeWriter                     out;
....
public final void write(Object object) {
        if (object == null) {
            out.writeNull();
            return;
        }

        Class clazz = object.getClass();
        ObjectSerializer writer = getObjectWriter(clazz);

        try {
            writer.write(this, object, null, null, 0);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

最后简述一下write的方法如何实现的。以ListSerializer的write为例:

假设我们的VO是如下定义的:

    static class Person{
        private int id;
        private String name;

        public Person(int id, String name) {
            this.id = id;
            this.name = name;
        }
        public int getId() { return id; }
        public void setId(int id) { this.id = id; }
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        @Override
        public String toString() {
            return "Person{" + "id=" + id + ", name='" + name + '\'' + '}';
        }
    }

1、ListSerializer关键起点:

out.append('['); 
for (int i = 0, size = list.size(); i < size; ++i) {
...
}
out.append(']');

2、首先创建对象createJavaBeanSerializer,

public final ObjectSerializer createJavaBeanSerializer(Class clazz) {
	    SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy, fieldBased);
	    if (beanInfo.fields.length == 0 && Iterable.class.isAssignableFrom(clazz)) {
	        return MiscCodec.instance;
	    }

	    return createJavaBeanSerializer(beanInfo);
	}

3、上述代码的TypeUtils.buildBeanInfo方法中存在下面代码中所列出的关键方法,就是根据反射获取所有的字段

    public static void  parserAllFieldToCache(Class clazz,Map fieldCacheMap){
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            if (!fieldCacheMap.containsKey(fieldName)) {
                fieldCacheMap.put(fieldName, field);
            }
        }
        if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) {
            parserAllFieldToCache(clazz.getSuperclass(), fieldCacheMap);
        }
    }

 在这一步,还要再按照getName,getId等bean的方法去获取bean的存在get方法的成员变量名,具体获取方式就是按照get3个字后面的大写字母匹配。

            if(methodName.startsWith("get")){
                if(methodName.length() < 4){
                    continue;
                }
                if(methodName.equals("getClass")){
                    continue;
                }
                if(methodName.equals("getDeclaringClass") && clazz.isEnum()){
                    continue;
                }
                char c3 = methodName.charAt(3);
                String propertyName;
                if(Character.isUpperCase(c3) //
                        || c3 > 512 // for unicode method name
                        ){
                    if(compatibleWithJavaBean){
                        propertyName = decapitalize(methodName.substring(3));
                    } else{
                        propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
                    }
                    propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 3);
                } else if(c3 == '_'){
                    propertyName = methodName.substring(4);
                } else if(c3 == 'f'){
                    propertyName = methodName.substring(3);
                } else if(methodName.length() >= 5 && Character.isUpperCase(methodName.charAt(4))){
                    propertyName = decapitalize(methodName.substring(3));
                } else{
                    continue;
                }
                boolean ignore = isJSONTypeIgnore(clazz, propertyName);
                if(ignore){
                    continue;
                }
                //假如bean的field很多的情况一下,轮询时将大大降低效率
                Field field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
                if(field == null && propertyName.length() > 1){
                    char ch = propertyName.charAt(1);
                    if(ch >= 'A' && ch <= 'Z'){
                        String javaBeanCompatiblePropertyName = decapitalize(methodName.substring(3));
                        field = ParserConfig.getFieldFromCache(javaBeanCompatiblePropertyName, fieldCacheMap);
                    }
                }
                JSONField fieldAnnotation = null;
                if(field != null){
                    fieldAnnotation = field.getAnnotation(JSONField.class);
                    if(fieldAnnotation != null){
                        if(!fieldAnnotation.serialize()){
                            continue;
                        }
                        ordinal = fieldAnnotation.ordinal();
                        serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
                        parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
                        if(fieldAnnotation.name().length() != 0){
                            propertyName = fieldAnnotation.name();
                            if(aliasMap != null){
                                propertyName = aliasMap.get(propertyName);
                                if(propertyName == null){
                                    continue;
                                }
                            }
                        }
                        if(fieldAnnotation.label().length() != 0){
                            label = fieldAnnotation.label();
                        }
                    }
                }
                if(aliasMap != null){
                    propertyName = aliasMap.get(propertyName);
                    if(propertyName == null){
                        continue;
                    }
                }
                if(propertyNamingStrategy != null){
                    propertyName = propertyNamingStrategy.translate(propertyName);
                }
                FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures,
                        annotation, fieldAnnotation, label);
                fieldInfoMap.put(propertyName, fieldInfo);
            }

 4、根据字段生成json格式的字符

            final char startSeperator = writeAsArray ? '[' : '{';
            final char endSeperator = writeAsArray ? ']' : '}';
            if (!unwrapped) {
                out.append(startSeperator);
            }

...
            if (!unwrapped) {
                out.append(endSeperator);
            }
    protected char[] genFieldNameChars() {
        int nameLen = this.name.length();
        char[] name_chars = new char[nameLen + 3];
        this.name.getChars(0, this.name.length(), name_chars, 1);
        name_chars[0] = '"';
        name_chars[nameLen + 1] = '"';
        name_chars[nameLen + 2] = ':';
        return name_chars;
    }

初步研究fastjson 的 toJSONString方法及其原理_第2张图片

 在out中write字段

if (!fieldInfo.unwrapped) {
    if (directWritePrefix) {
        out.write(fieldInfo.name_chars, 0, fieldInfo.name_chars.length);
    } else {
        fieldSerializer.writePrefix(serializer);
    }
}

 可以看出生成了字符数组:{"name":}

4、接下来按照VO的数据类型再用工厂生成ObjectSerializer,继续解析拼接字符串。如果获取的是int类型的数据,则创建IntegerCodec实例,调用他的write方法:

public class IntegerCodec implements ObjectSerializer, ObjectDeserializer {
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;
        Number value = (Number) object;
        if (value == null) {
            out.writeNull(SerializerFeature.WriteNullNumberAsZero);
            return;
        }
        if (object instanceof Long) {
            out.writeLong(value.longValue());
        } else {
            out.writeInt(value.intValue());
        }
        if (out.isEnabled(SerializerFeature.WriteClassName)) {
            Class clazz = value.getClass();
            if (clazz == Byte.class) {
                out.write('B');
            } else if (clazz == Short.class) {
                out.write('S');
            }
        }
    }

 

5、生成value以后接下来生成下一个字段的value,在两个字段的value之间是","

在javaBeanSerializer里的代码片段

                if (commaFlag) {
                    if (fieldInfo.unwrapped
                            && propertyValue instanceof Map
                            && ((Map) propertyValue).size() == 0) {
                        continue;
                    }

                    out.write(',');
                    if (out.isEnabled(SerializerFeature.PrettyFormat)) {
                        serializer.println();
                    }

 6、当List中一个对象的所有字段全都write后,最后调用out.appent添加结束大括号

            if (!unwrapped) {
                out.append(endSeperator);
            }

7、然后继续下一次循环。。

你可能感兴趣的:(开发点滴)