Fastjson2基础使用以及底层序列化/反序列化实现探究

news2024/11/16 11:33:28

1 Fastjson2简介

Fastjson2Fastjson的升级版,特征:

  • 协议支持:支持JSON/JSONB两种协议
  • 部分解析:可以使用JSONPath进行部分解析获取需要的值
  • 语言支持:Java/Kotlin
  • 场景支持:Android8+/服务端
  • 其他特性支持:Graal Native-ImageJSON Schema

2 基础使用

2.1 测试环境

环境:

  • JDK版本:1.8.0_341
  • Fastjson2版本:2.0.19

测试类:

@Builder
@Data
@ToString
public class Entity {
    private String field1;
    private Integer field2;
}

2.2 JSON序列化

System.out.println(JSON.toJSONString(entity));

2.3 JSON反序列化

System.out.println(JSON.parseObject(str,Entity.class));

2.4 JSONB序列化

byte[] bytes = JSONB.toBytes(entity);

2.5 JSONB反序列化

System.out.println(JSONB.parseObject(bytes,Entity.class));

2.6 JSON Schema

JSON Schema可用于反序列化时对JSON字段进行验证使用,配置Schema可以通过@JSONField/@JSONType,这里以@JSONField为例:

public class Entity {
    private String field1;
    @JSONField(schema = "{'minimum':0,'maximum':100}")
    private Integer field2;
}

测试代码:

Entity entity1 = Entity.builder().field2(-1).build();
Entity entity2 = Entity.builder().field2(50).build();
Entity entity3 = Entity.builder().field2(101).build();

String str1 = JSON.toJSONString(entity1);
String str2 = JSON.toJSONString(entity2);
String str3 = JSON.toJSONString(entity3);

try {
    JSON.parseObject(str1, Entity.class);
} catch (Exception e) {
    e.printStackTrace();
}

JSON.parseObject(str2, Entity.class);

try {
    JSON.parseObject(str3, Entity.class);
} catch (Exception e) {
    e.printStackTrace();
}

输出:

2.7 JSONPath

JSONPath可用于部分解析JSON字符串,示例:

Entity entity = Entity.builder().field1("a").field2(2).build();
// $符号表示根对象
// $.field1表示根对象的field1属性
System.out.println(JSONPath.eval(entity,"$.field1"));
System.out.println(JSONPath.eval(entity,"$.field2"));

List<Entity> list = new ArrayList<>();
list.add(Entity.builder().field1("entity1").field2(1).build());
list.add(Entity.builder().field1("entity2").field2(2).build());
// 如果传的是List,支持通过下标解析
// 此处是返回[0,0]下标范围内的值
List<Entity> names = (List<Entity>)JSONPath.eval(list,"[0,0]");
System.out.println(names.get(0));

详细的解析语法以及更多例子请参考官方文档。

2.8 AutoType

AutoType是在序列化的时候带上类型的一种机制,这样在反序列化时就不需要传入类型,实现类型自动识别,例子:

Entity entity = Entity.builder().field1("a").field2(2).build();
String str = JSON.toJSONString(entity, JSONWriter.Feature.WriteClassName);
System.out.println(str);
System.out.println(JSON.parseObject(str, Object.class, JSONReader.Feature.SupportAutoType));

输出:

由于在Fastjson1中出现过AutoType漏洞,因此官方提供了一个JVM参数完全禁止(safeMode功能):

-Dfastjson2.parser.safeMode=true

3 底层实现探究

3.1 序列化

3.1.1 概览

序列化的实现可以参考官方的一张类图:

大概流程如下:

  • 获取ObjectWriter
  • 如果从ObjectWriterProvider缓存有ObjectWriter,直接提取
  • 如果ObjectWriterProvider缓存没有ObjectWriter,构造对应的ObjectWriter,并缓存
  • 获取到ObjectWriter后,将JavaBean对象写入JSONWriter
  • JSONWriter对基础类型进行写入
  • 返回结果

3.1.2 入口

这里的序列化探究以JSON.toJSONString(Object object)作为入口:

static String toJSONString(Object object) {
	// 初始化ObjectWriterProvider
    JSONWriter.Context writeContext = new JSONWriter.Context(JSONFactory.defaultObjectWriterProvider);
    // 格式化控制
    boolean pretty = (writeContext.features & com.alibaba.fastjson2.JSONWriter.Feature.PrettyFormat.mask) != 0L;
    Object jsonWriter;
    // 默认有三个JSONWriter,JDK8一个,针对JDK9之后的byte[]实现的字符串优化也有一个,还有一个基于char[]实现的UTF16
    if (JDKUtils.JVM_VERSION == 8) {
        jsonWriter = new JSONWriterUTF16JDK8(writeContext);
    } else if ((writeContext.features & com.alibaba.fastjson2.JSONWriter.Feature.OptimizedForAscii.mask) != 0L) {
        jsonWriter = new JSONWriterUTF8JDK9(writeContext);
    } else {
        jsonWriter = new JSONWriterUTF16(writeContext);
    }

    try {
    	// 格式化控制
        JSONWriter writer = pretty ? new JSONWriterPretty((JSONWriter)jsonWriter) : jsonWriter;

        String var12;
        try {
            if (object == null) {
            	// null的话直接写入"null"字符串
                ((JSONWriter)writer).writeNull();
            } else {
            	// 设置根对象
                ((JSONWriter)writer).setRootObject(object);
                Class<?> valueClass = object.getClass();
                if (valueClass == JSONObject.class) {
                	// 如果目标类是JSNOObject,直接调用writer的write方法
                    ((JSONWriter)writer).write((JSONObject)object);
                } else {
                	// 如果不是
                    JSONWriter.Context context = ((JSONWriter)writer).context;
                    boolean fieldBased = (context.features & com.alibaba.fastjson2.JSONWriter.Feature.FieldBased.mask) != 0L;
                    // 通过Provider获取ObjectWriter
                    ObjectWriter<?> objectWriter = context.provider.getObjectWriter(valueClass, valueClass, fieldBased);
                    // ObjectWriter将数据写入JSONWriter
                    objectWriter.write((JSONWriter)writer, object, (Object)null, (Type)null, 0L);
                }
            }
			// 结果
            var12 = writer.toString();
			// 下面的代码与序列化关系不大,可以不看
        } catch (Throwable var10) {
            if (writer != null) {
                try {
                    ((JSONWriter)writer).close();
                } catch (Throwable var9) {
                    var10.addSuppressed(var9);
                }
            }

            throw var10;
        }

        if (writer != null) {
            ((JSONWriter)writer).close();
        }

        return var12;
    } catch (NumberFormatException | NullPointerException var11) {
        throw new JSONException("JSON#toJSONString cannot serialize '" + object + "'", var11);
    }
}

3.1.3 获取ObjectWriterProvider

JSON.toJSONString()入口:

JSONWriter.Context writeContext = new JSONWriter.Context(JSONFactory.defaultObjectWriterProvider);

其中会调用默认的构造方法初始化ObjectWriterProvider

public ObjectWriterProvider() {
    this.init();
    ObjectWriterCreator creator = null;
    switch (JSONFactory.CREATOR) {
        case "reflect":
            creator = ObjectWriterCreator.INSTANCE;
            break;
        case "lambda":
            creator = ObjectWriterCreatorLambda.INSTANCE;
            break;
        case "asm":
        default:
            try {
                creator = ObjectWriterCreatorASM.INSTANCE;
            } catch (Throwable var5) {
            }

            if (creator == null) {
                creator = ObjectWriterCreatorLambda.INSTANCE;
            }
    }

    this.creator = (ObjectWriterCreator)creator;
}

ObjectWriterCreator采取的是单例模式,默认采用ASM动态字节码实现。

3.1.4 获取ObjectWriter

有了ObjectWriterProvider后,下一步就是获取ObjectWriter,也就是JSON.toJSONString()中的:

JSONWriter.Context context = ((JSONWriter)writer).context;
boolean fieldBased = (context.features & com.alibaba.fastjson2.JSONWriter.Feature.FieldBased.mask) != 0L;
ObjectWriter<?> objectWriter = context.provider.getObjectWriter(valueClass, valueClass, fieldBased);

getObjectWriter()如下:

public ObjectWriter getObjectWriter(Type objectType, Class objectClass, boolean fieldBased) {
	// fieldBased是基于字段序列化的意思
	// false的话表示基于getter序列化
	// 根据不同的类型从不同的缓存map中获取
    ObjectWriter objectWriter = fieldBased ? (ObjectWriter)this.cacheFieldBased.get(objectType) : (ObjectWriter)this.cache.get(objectType);
    // 首次获取应该为null
    if (objectWriter != null) {
        return (ObjectWriter)objectWriter;
    } else {
    	// 这个useModules布尔变量笔者不太了解
    	// 这里的逻辑是 基于字段反序列化 并且 目标class不为空 并且 目标class可以赋值给Iterable 并且 目标class不能赋值给class
        boolean useModules = true;
        if (fieldBased && objectClass != null && Iterable.class.isAssignableFrom(objectClass) && !Collection.class.isAssignableFrom(objectClass)) {
            useModules = false;
        }
		
		// 这里的例子是true
        if (useModules) {
            for(int i = 0; i < this.modules.size(); ++i) {
            	// 获取ObjectWriterModule
                ObjectWriterModule module = (ObjectWriterModule)this.modules.get(i);
                objectWriter = module.getObjectWriter(objectType, objectClass);
                // 为null
                if (objectWriter != null) {
                    ObjectWriter previous = fieldBased ? (ObjectWriter)this.cacheFieldBased.putIfAbsent(objectType, objectWriter) : (ObjectWriter)this.cache.putIfAbsent(objectType, objectWriter);
                    if (previous != null) {
                        objectWriter = previous;
                    }

                    return (ObjectWriter)objectWriter;
                }
            }
        }

		// 第一次执行暂时还拿不到ObjectWriter,这里的条件全部符合
        if (objectWriter == null && objectClass != null && !fieldBased) {
            switch (objectClass.getName()) {
            	// 针对Guava库的map内置了ObjectWriter
                case "com.google.common.collect.HashMultimap":
                case "com.google.common.collect.LinkedListMultimap":
                case "com.google.common.collect.LinkedHashMultimap":
                case "com.google.common.collect.ArrayListMultimap":
                case "com.google.common.collect.TreeMultimap":
                    objectWriter = GuavaSupport.createAsMapWriter(objectClass);
                    break;
                // 不是JSONObject类
                case "com.alibaba.fastjson.JSONObject":
                    objectWriter = ObjectWriterImplMap.of(objectClass);
            }
        }
		
		// ObjectWriter还没拿到
        if (objectWriter == null) {
        	// 第一次拿需要通过ObjectWriterCreator()去创建
            ObjectWriterCreator creator = this.getCreator();
            if (objectClass == null) {
                objectClass = TypeUtils.getMapping(objectType);
            }
			
			// 创建ObjectWriter
			// ObjectWriter的里面会创建FieldWriter,这里面的逻辑很长,经过一些列复杂逻辑的判断,再针对字段获取
            objectWriter = creator.createObjectWriter(objectClass, fieldBased ? Feature.FieldBased.mask : 0L, this);
            // 放入缓存
            ObjectWriter previous = fieldBased ? (ObjectWriter)this.cacheFieldBased.putIfAbsent(objectType, objectWriter) : (ObjectWriter)this.cache.putIfAbsent(objectType, objectWriter);
            if (previous != null) {
                objectWriter = previous;
            }
        }

        return (ObjectWriter)objectWriter;
    }
}

其中FiledWriter获取逻辑如下:

// ObjectWriterCreatorASM.java 236行左右的位置
BeanUtils.fields(objectClass, (field) -> {
    if (fieldBased || Modifier.isPublic(field.getModifiers())) {
        fieldInfo.init();
        // 创建FieldWriter
        FieldWriter fieldWriter = this.creteFieldWriter(objectClass, writerFeatures, provider.modules, beanInfo, fieldInfo, field);
        if (fieldWriter != null) {
        	// 放入缓存
            fieldWriterMap.putIfAbsent(fieldWriter.fieldName, fieldWriter);
        }

    }
});

3.1.5 write()操作

获取到ObjectWriter之后,就可以进行write()操作了,JSON.toJSONString()入口:

objectWriter.write((JSONWriter)writer, object, (Object)null, (Type)null, 0L);

由于自定义类的ObjectWriter是运行时拿到的,无法通过调试获取到,但是可以通过内置的ObjectWriter来判断大概的write()流程:

比如LocalDateWriterwrite()如下:

public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
    try {
        int year = (Integer)this.getYear.invoke(object);
        int monthOfYear = (Integer)this.getMonthOfYear.invoke(object);
        int dayOfMonth = (Integer)this.getDayOfMonth.invoke(object);
        Object chronology = this.getChronology.invoke(object);
        if (chronology != this.utc && chronology != null) {
            jsonWriter.startObject();
            // 写入key
            jsonWriter.writeName("year");
            // 写入value
            jsonWriter.writeInt32(year);
            jsonWriter.writeName("month");
            jsonWriter.writeInt32(monthOfYear);
            jsonWriter.writeName("day");
            jsonWriter.writeInt32(dayOfMonth);
            jsonWriter.writeName("chronology");
            jsonWriter.writeAny(chronology);
            jsonWriter.endObject();
        } else {
            LocalDate localDate = LocalDate.of(year, monthOfYear, dayOfMonth);
            DateTimeFormatter formatter = this.getDateFormatter();
            if (formatter == null) {
                formatter = jsonWriter.getContext().getDateFormatter();
            }

            if (formatter == null) {
                jsonWriter.writeLocalDate(localDate);
            } else {
                String str = formatter.format(localDate);
                jsonWriter.writeString(str);
            }
        }
    } catch (InvocationTargetException | IllegalAccessException var14) {
        throw new JSONException("write LocalDateWriter error", var14);
    }
}

根据getter获取字段值并调用对应的Writer去写JSON

3.2 反序列化

3.2.1 概览

反序列化也可以参考官方的一张图:

大概流程与序列化类似:

  • 获取ObjectReader
  • 如果ObjectReaderProvider有缓存,从缓存提取
  • 如果ObjectReaderProvider没有缓存,创建ObjectReader并且缓存到ObjectReaderProvider
  • 通过JSONReader得到Object
  • 返回结果

3.2.2 入口

Entity entity = Entity.builder().field1("a").field2(2).build();
String str = JSON.toJSONString(entity);
System.out.println(JSON.parseObject(str,Entity.class));

其中parseObject()如下:

static <T> T parseObject(String text, Class<T> clazz) {
    if (text != null && !text.isEmpty()) {
    	// 获取JSONReader
        JSONReader reader = JSONReader.of(text);

        Object var7;
        try {
            JSONReader.Context context = reader.context;
            // 判断是否基于字段反序列化
            boolean fieldBased = (context.features & Feature.FieldBased.mask) != 0L;
            // 通过ObjectReaderProvider获取ObjectReader
            // 这个context看起来和ObjectReaderProvider无关,实际上内部实现Context包含了ObjectReaderProvider
            ObjectReader<T> objectReader = context.provider.getObjectReader(clazz, fieldBased);
            // 反序列化核心方法
            T object = objectReader.readObject(reader, (Type)null, (Object)null, 0L);
            if (reader.resolveTasks != null) {
                reader.handleResolveTasks(object);
            }

            if (reader.ch != 26 && (reader.context.features & Feature.IgnoreCheckClose.mask) == 0L) {
                throw new JSONException(reader.info("input not end"));
            }

            var7 = object;
        } catch (Throwable var9) {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Throwable var8) {
                    var9.addSuppressed(var8);
                }
            }

            throw var9;
        }

        if (reader != null) {
            reader.close();
        }

        return var7;
    } else {
        return null;
    }
}

3.2.3 获取JSONReader

JSON.parseObject()入口:

JSONReader reader = JSONReader.of(text);

其中JSONReader.of()实现如下:

public static JSONReader of(String str) {
    if (str == null) {
        throw new NullPointerException();
    } else {
    	// 创建Context
    	// Context内部包含了ObjectReaderProvider
        Context context = JSONFactory.createReadContext();
        int length;
        // 测试环境JDK8,此处if不成立
        if (JDKUtils.JVM_VERSION > 8 && JDKUtils.UNSAFE_SUPPORT) {
            try {
                length = JDKUtils.STRING_CODER != null ? JDKUtils.STRING_CODER.applyAsInt(str) : UnsafeUtils.getStringCoder(str);
                if (length == 0) {
                    byte[] bytes = JDKUtils.STRING_VALUE != null ? (byte[])JDKUtils.STRING_VALUE.apply(str) : UnsafeUtils.getStringValue(str);
                    return new JSONReaderASCII(context, str, bytes, 0, bytes.length);
                }
            } catch (Exception var4) {
                throw new JSONException("unsafe get String.coder error");
            }
        }

        length = str.length();
        char[] chars;
        // 测试环境JDK8
        if (JDKUtils.JVM_VERSION == 8) {
        	// 获取char array
            chars = JDKUtils.getCharArray(str);
        } else {
            chars = str.toCharArray();
        }
		
		// 由于JDK8的String还是使用char[]实现的,所以返回UTF16的JSONReader
        return new JSONReaderUTF16(context, str, chars, 0, length);
    }
}

3.2.4 获取ObjectReader

JSON.parseObject()入口:

ObjectReader<T> objectReader = context.provider.getObjectReader(clazz, fieldBased);

getObjectReader()如下:

public ObjectReader getObjectReader(Type objectType, boolean fieldBased) {
    if (objectType == null) {
        objectType = Object.class;
    }

	// 有缓存直接从缓存提取
    ObjectReader objectReader = fieldBased ? (ObjectReader)this.cacheFieldBased.get(objectType) : (ObjectReader)this.cache.get(objectType);
    // 第一次获取ObjectReader为null
    if (objectReader != null) {
        return objectReader;
    } else {
        Iterator var4 = this.modules.iterator();

        ObjectReader previous;
        while(var4.hasNext()) {
            ObjectReaderModule module = (ObjectReaderModule)var4.next();
            // 获取到的ObjectReader为null
            objectReader = module.getObjectReader(this, (Type)objectType);
            if (objectReader != null) {
                previous = fieldBased ? (ObjectReader)this.cacheFieldBased.putIfAbsent(objectType, objectReader) : (ObjectReader)this.cache.putIfAbsent(objectType, objectReader);
                if (previous != null) {
                    objectReader = previous;
                }

                return objectReader;
            }
        }

        Type rawType;
        // 条件不符合
        if (objectType instanceof TypeVariable) {
            Type[] bounds = ((TypeVariable)objectType).getBounds();
            if (bounds.length > 0) {
                rawType = bounds[0];
                if (rawType instanceof Class) {
                    previous = this.getObjectReader(rawType, fieldBased);
                    if (previous != null) {
                        ObjectReader previous = this.getPreviousObjectReader(fieldBased, (Type)objectType, previous);
                        if (previous != null) {
                            previous = previous;
                        }

                        return previous;
                    }
                }
            }
        }
		
		// 条件不符合
        if (objectType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType)objectType;
            rawType = parameterizedType.getRawType();
            Type[] typeArguments = parameterizedType.getActualTypeArguments();
            if (rawType instanceof Class) {
                Class rawClass = (Class)rawType;
                boolean generic = false;

                for(Class clazz = rawClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
                    if (clazz.getTypeParameters().length > 0) {
                        generic = true;
                        break;
                    }
                }

                if (typeArguments.length == 0 || !generic) {
                    ObjectReader rawClassReader = this.getObjectReader(rawClass, fieldBased);
                    if (rawClassReader != null) {
                        ObjectReader previous = this.getPreviousObjectReader(fieldBased, (Type)objectType, rawClassReader);
                        if (previous != null) {
                            rawClassReader = previous;
                        }

                        return rawClassReader;
                    }
                }
            }
        }

        Class<?> objectClass = TypeUtils.getMapping((Type)objectType);
        String className = objectClass.getName();
        if (objectReader == null && !fieldBased) {
            switch (className) {
            	// 针对Guava的MultiMap,这里的条件不符合
                case "com.google.common.collect.ArrayListMultimap":
                    objectReader = ObjectReaderImplMap.of((Type)null, objectClass, 0L);
            }
        }
		
		// ObjectReader为null
        if (objectReader == null) {
        	// 获取ObjectReaderCreator
            ObjectReaderCreator creator = this.getCreator();
            // 创建ObjectReader
            objectReader = creator.createObjectReader(objectClass, (Type)objectType, fieldBased, this);
        }

        previous = this.getPreviousObjectReader(fieldBased, (Type)objectType, objectReader);
        if (previous != null) {
            objectReader = previous;
        }

        return objectReader;
    }
}

在创建ObjectReader的同时,会在其中创建FieldReader

// ObjectReaderCreator.java 453
FieldReader[] fieldReaderArray = this.createFieldReaders(objectClass, objectType, beanInfo, fieldBased, provider);

3.2.5 read()操作

有了ObjectReader之后就可以进行具体的read()操作了,JSON.parseObject()入口:

T object = objectReader.readObject(reader, (Type)null, (Object)null, 0L);

此处的readObject()如下:

// ObjectReaderNoneDefaultConstructor.java 171行
public T readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
	// 判断是否带有JSONReader.Feature.ErrorOnNoneSerializable
    if (!this.serializable) {
        jsonReader.errorOnNoneSerializable(this.objectClass);
    }

	// 是否JSONB,不符合
    if (jsonReader.isJSONB()) {
        return this.readJSONBObject(jsonReader, fieldType, fieldName, 0L);
    } else if (jsonReader.isArray() && jsonReader.isSupportBeanArray(features | this.features)) {
    	// 是数组而且支持JSONReader.Feature.SupportArrayToBean,不符合
        jsonReader.next();
        LinkedHashMap<Long, Object> valueMap = null;

        for(int i = 0; i < this.fieldReaders.length; ++i) {
            Object fieldValue = this.fieldReaders[i].readFieldValue(jsonReader);
            if (valueMap == null) {
                valueMap = new LinkedHashMap();
            }

            long hash = this.fieldReaders[i].fieldNameHash;
            valueMap.put(hash, fieldValue);
        }

        if (!jsonReader.nextIfMatch(']')) {
            throw new JSONException(jsonReader.info("array not end, " + jsonReader.current()));
        } else {
            jsonReader.nextIfMatch(',');
            return this.createInstanceNoneDefaultConstructor((Map)(valueMap == null ? Collections.emptyMap() : valueMap));
        }
    } else {
    	// 读取字符
        boolean objectStart = jsonReader.nextIfObjectStart();
        // 条件为false,进入else
        if (!objectStart && !jsonReader.isTypeRedirect() && jsonReader.nextIfEmptyString()) {
            return null;
        } else {
        	// 获取Context,读取其中的Features
            JSONReader.Context context = jsonReader.getContext();
            long featuresAll = this.features | features | context.getFeatures();
            // 此处存储对象的值
            // key是字段的long哈希值,哈希采取的是fnv1a 64算法生成的
            // value是字段的具体值
            LinkedHashMap<Long, Object> valueMap = null;

			// 读取
            for(int i = 0; !jsonReader.nextIfMatch('}'); ++i) {
            	// 读取字段名对应的hashCode
                long hashCode = jsonReader.readFieldNameHashCode();
                if (hashCode != 0L) {
                    if (hashCode == this.typeKeyHashCode && i == 0) {
                        long typeHash = jsonReader.readTypeHashCode();
                        // 此处if条件不符合
                        if (typeHash != this.typeNameHash) {
                            boolean supportAutoType = (featuresAll & Feature.SupportAutoType.mask) != 0L;
                            ObjectReader autoTypeObjectReader;
                            String typeName;
                            if (supportAutoType) {
                                autoTypeObjectReader = context.getObjectReaderAutoType(typeHash);
                                if (autoTypeObjectReader == null) {
                                    typeName = jsonReader.getString();
                                    autoTypeObjectReader = context.getObjectReaderAutoType(typeName, this.objectClass, this.features);
                                }
                            } else {
                                typeName = jsonReader.getString();
                                autoTypeObjectReader = context.getObjectReaderAutoType(typeName, this.objectClass);
                            }

                            if (autoTypeObjectReader == null) {
                                typeName = jsonReader.getString();
                                autoTypeObjectReader = context.getObjectReaderAutoType(typeName, this.objectClass, this.features);
                            }

                            if (autoTypeObjectReader != null) {
                                Object object = autoTypeObjectReader.readObject(jsonReader, fieldType, fieldName, 0L);
                                jsonReader.nextIfMatch(',');
                                return object;
                            }
                        }
                    } else {
                    	// 获取字段名哈希对应的FieldReader
                        FieldReader fieldReader = this.getFieldReader(hashCode);
                       	// 条件不符合
                        if (fieldReader == null && (featuresAll & Feature.SupportSmartMatch.mask) != 0L) {
                            long hashCodeLCase = jsonReader.getNameHashCodeLCase();
                            if (hashCodeLCase != hashCode) {
                                fieldReader = this.getFieldReaderLCase(hashCodeLCase);
                            }
                        }
						
						// fieldReader不为null
                        if (fieldReader == null) {
                            this.processExtra(jsonReader, (Object)null);
                        } else {
                        	// 读取字段值
                            Object fieldValue = fieldReader.readFieldValue(jsonReader);
                            if (valueMap == null) {
                                valueMap = new LinkedHashMap();
                            }

                            long hash;
                            if (fieldReader instanceof FieldReaderObjectParam) {
                                hash = ((FieldReaderObjectParam)fieldReader).paramNameHash;
                            } else {
                                hash = fieldReader.fieldNameHash;
                            }
							// 写入
                            valueMap.put(hash, fieldValue);
                        }
                    }
                }
            }

			// 构造对象
            T object = this.createInstanceNoneDefaultConstructor((Map)(valueMap == null ? Collections.emptyMap() : valueMap));
            if (this.setterFieldReaders != null && valueMap != null) {
                for(int i = 0; i < this.setterFieldReaders.length; ++i) {
                    FieldReader fieldReader = this.setterFieldReaders[i];
                    // 读取字段值
                    Object fieldValue = valueMap.get(fieldReader.fieldNameHash);
                    if (fieldValue != null) {
                    	// 通过setter注入
                        fieldReader.accept(object, fieldValue);
                    }
                }
            }

            jsonReader.nextIfMatch(',');
            return object;
        }
    }
}

4 结尾

其实文章中很多细节的地方由于篇幅的限制无法过于详细的解释,比如内置的各类型的Reader/Writer具体是如何获取值进行序列化/反序列操作的,想要深入探究这部分就只能自己去挖源码了。另外需要注意的是,文章的环境是在JDK8下的,由于Fastjson2在不同的JDK下会有不同的序列化实现,因此仅供参考。

最后,关于性能的比较,可以参考官方的比较基准。

5 参考

  • Fastjson2 Github
  • Fastjson2 Wiki

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/356147.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python基础知识有哪些需要背(记住是基础知识)我是初学者

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;一个有趣的事情&#xff0c;一个有趣的事情&#xff0c;今天让我们一起来看看吧&#xff01; 1、python基础知识有哪些需要背&#xff08;记住是基础知识&#xff09;我是初学者 或看好Python的广阔前景&#xff0c;或…

RabbitMQ 入门到应用 ( 五 ) 应用

6.更多应用 6.1.AmqpAdmin 工具类 可以通过Spring的Autowired 注入 AmqpAdmin 工具类 , 通过这个工具类创建 队列, 交换机及绑定 import org.springframework.amqp.core.AmqpAdmin; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Di…

python基于django微信小程序的适老化老人健康预警小程序

随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代, 适老化老人健康预警微信小程序就是信息时代变革中的产物之一。 任何系统都要遵…

Spring国际化实现

Java国际化 Java使用Unicode来处理所有字符。 Locales 国际化主要涉及的是数字、日期、金额等。 有若干个专门负责格式处理的类。为了对格式进行控制&#xff0c;可以使用Locale类。它描述了&#xff1a; 一种语言一个位置(通常包含)一段脚本(可选&#xff0c;自Java SE7开…

CMMI之需求开发流程

需求开发&#xff08;Requirement Development, RD&#xff09;的目的是通过调查与分析&#xff0c;获取用户需求并定义产品需求。需求开发过程域是SPP模型的重要组成部分。本规范阐述了需求开发过程域的两个主要规程&#xff1a; 需求调查 [SPP-PROC-RM-SURVEY] 需求定义 [SPP…

消失的数字【C语言】

题目&#xff1a; 数组nums包含从0到n的所有整数&#xff0c;但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗&#xff1f; 解法&#xff1a; int missingNumber(int* nums, int numsSize){int val0;for(int i0;i<numsSize;i){val^nums[i];}fo…

Vue3之条件渲染

1.何为条件渲染 条件渲染就是在指定的条件下&#xff0c;渲染出指定的UI。比如当我们显示主页的时候&#xff0c;应该隐藏掉登录等一系列不相干的UI元素。即UI元素只在特定条件下进行显示。而在VUE3中&#xff0c;这种UI元素的显示和隐藏可以通过两个关键字&#xff0c;v-if 和…

Qt动画框架详解

目录1.前言2.原理3.属性动画4.并行执行的动画5.顺序执行的动画6.扩展属性动画支持的数据类型1.前言 为软件适当的添加一些动画&#xff0c;能够提高软件的用户体验。在使用Qt框架开发软件时&#xff0c;我们可以用Qt提供的动画框架来为QWidget等UI元素添加动画效果。本文从动画…

程序员和他的女朋友一起创建了价值 150,000,000 美元的网站

本篇文章讲述了Otis和Elizabeth Chandler创办Goodreads.com的故事。他们从小就爱读书&#xff0c;创办网站前他们的困惑是没有很多人在线分享书评。Otis和Elizabeth觉得如果有一个地方把所有人的评论和评价收集起来&#xff0c;那将会很有价值。奥蒂斯和伊丽莎白从小就喜欢读书…

MMKV与mmap:全方位解析

概述 MMKV 是基于 mmap 内存映射的移动端通用 key-value 组件&#xff0c;底层序列化/反序列化使用 protobuf 实现&#xff0c;性能高&#xff0c;稳定性强。从 2015 年中至今&#xff0c;在 iOS 微信上使用已有近 3 年&#xff0c;其性能和稳定性经过了时间的验证。近期已移植…

海量数据相似数据查询方法

1、海量文本常见 海量文本场景&#xff0c;如何寻找一个doc的topn相似doc&#xff0c;一般存在2个问题&#xff0c; 1)、两两对比时间o(n^2) 2)、高维向量比较比较耗时。 文本集可以看成(doc,word)稀疏矩阵&#xff0c;一般常见的方法是构建到排索引&#xff0c;然后进行归并…

论文投稿指南——中文核心期刊推荐(社会学)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

【论文精读】DeepWalk: Online Learning of Social Representations

DeepWalk: Online Learning of Social Representations 本文是我参加Datawhale的CS224W图机器学习时的笔记&#xff0c;第一次学习图机器学习&#xff0c;对DeepWalk这篇开山之作的理解。 论文的三位作者均来自纽约州立大学石溪分校&#xff0c;杨振宁和丘成桐也曾在此教学。 …

JavaScript内存泄露和垃圾回收机制

1、是什么&#xff1f;内存泄露&#xff08;Memory leak&#xff09;是在计算机科学中&#xff0c;由于疏忽或错误造成程序未能释放已经不再使用的内存。并非指内存在物理上的消失&#xff0c;而是应用程序分配某段内存后&#xff0c;由于设计错误&#xff0c;导致在释放该段内…

Spring Boot 项目介绍

Spring Boot 项目介绍 作为学习过 Java 的软件开发者&#xff0c;相信都知道 Spring 这一伟大的框架&#xff0c;它所拥有的强大功能之一就是可以集成各种开源软件。但随着互联网的高速发展&#xff0c;各种框架层出不穷&#xff0c;这就对系统架构的灵活性、扩展性、可伸缩性…

【项目精选】基于JSP物流信息网(论文+源码+视频)

点击下载源码 近年来&#xff0c;随着时代的进步&#xff0c;社会随之不断发展&#xff0c;经济也快速发展起来了&#xff0c;人民的消费水平在不断地提高&#xff0c;平常的实体店消费已经不能满足人们的需求&#xff1b;在者&#xff0c;互联网技术的不断发展也为电子商务的兴…

CSS Houdini

前言 最近看了几篇文章&#xff0c;是关于 CSS Houdini 的。作为一个前端搬砖的还真不知道这玩意&#xff0c;虽然不知道的东西挺多的&#xff0c;但是这玩意有点高大上啊。 Houdini 是一组底层 API&#xff0c;它们公开了 CSS 引擎的各个部分&#xff0c;从而使开发人员能够通…

Matlab搭建AlexNet实现手写数字识别

Matlab搭建AlexNet实现手写数字识别 个人博客地址 文章目录Matlab搭建AlexNet实现手写数字识别环境内容步骤准备MNIST数据集数据预处理定义网络模型定义训练超参数网络训练和预测代码下载环境 Matlab 2020aWindows10 内容 使用Matlab对MNIST数据集进行预处理&#xff0c;搭建…

基于Spring Boot框架的人事管理系统的设计与实现(程序+详细文档)

大家好✌&#xff01;我是CZ淡陌。这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路&#xff01; &#x1f345;更多优质项目&#x1f447;&am…

面向六部十层电梯群控算法的研究

面向六部十层电梯群控算法的研究 赵大权&#xff0c;张翔宇 &#xff08;晋中学院 机械学院&#xff0c;山西 晋中 030619&#xff09; 摘 要&#xff1a; 在商业大楼和高层写字楼里&#xff0c;基于可编程逻辑控制器&#xff08;PLC&#xff09;对电梯运行进行控制是当前主流…