public ObjectReader createObjectReader()

in core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreator.java [1020:1337]


    public <T> ObjectReader<T> createObjectReader(
            Class<T> objectClass,
            Type objectType,
            boolean fieldBased,
            ObjectReaderProvider provider
    ) {
        BeanInfo beanInfo = new BeanInfo(provider);
        if (fieldBased) {
            beanInfo.readerFeatures |= JSONReader.Feature.FieldBased.mask;
        }

        for (ObjectReaderModule module : provider.modules) {
            ObjectReaderAnnotationProcessor annotationProcessor = module.getAnnotationProcessor();
            if (annotationProcessor != null) {
                annotationProcessor.getBeanInfo(beanInfo, objectClass);
            }
        }

        if (beanInfo.deserializer != null && ObjectReader.class.isAssignableFrom(beanInfo.deserializer)) {
            try {
                Constructor constructor = beanInfo.deserializer.getDeclaredConstructor();
                constructor.setAccessible(true);
                return (ObjectReader<T>) constructor.newInstance();
            } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
                     InvocationTargetException e) {
                throw new JSONException("create deserializer error", e);
            }
        }

        if (fieldBased) {
            beanInfo.readerFeatures |= JSONReader.Feature.FieldBased.mask;
        }

        if (Enum.class.isAssignableFrom(objectClass) && (beanInfo.createMethod == null || beanInfo.createMethod.getParameterCount() == 1)) {
            return createEnumReader(objectClass, beanInfo.createMethod, provider);
        }

        if (Throwable.class.isAssignableFrom(objectClass)) {
            fieldBased = false;
            beanInfo.readerFeatures |= JSONReader.Feature.IgnoreSetNullValue.mask;
        }

        if (objectClass == Class.class) {
            return ObjectReaderImplClass.INSTANCE;
        }

        if (fieldBased && objectClass.isInterface()) {
            fieldBased = false;
        }

        FieldReader[] fieldReaderArray = createFieldReaders(objectClass, objectType, beanInfo, fieldBased, provider);
        boolean allReadOnlyOrZero = true;
        for (int i = 0; i < fieldReaderArray.length; i++) {
            FieldReader fieldReader = fieldReaderArray[i];
            if (!fieldReader.isReadOnly()) {
                allReadOnlyOrZero = false;
                break;
            }
        }

        if (beanInfo.creatorConstructor != null || beanInfo.createMethod != null) {
            return createObjectReaderWithCreator(objectClass, objectType, provider, beanInfo);
        }

        if (beanInfo.builder != null) {
            return createObjectReaderWithBuilder(objectClass, objectType, provider, beanInfo);
        }

        Constructor creatorConstructor = null;

        final List<Constructor> alternateConstructors = new ArrayList<>();
        BeanUtils.constructor(objectClass, alternateConstructors::add);

        if (Throwable.class.isAssignableFrom(objectClass)) {
            return new ObjectReaderException<>(objectClass, alternateConstructors, fieldReaderArray);
        }

        Constructor defaultConstructor = null;

        Class<?> declaringClass = objectClass.getDeclaringClass();

        int index = -1;
        for (int i = 0; i < alternateConstructors.size(); i++) {
            Constructor constructor = alternateConstructors.get(i);

            if (constructor.getParameterCount() == 0) {
                defaultConstructor = constructor;
            }

            if (declaringClass != null
                    && constructor.getParameterCount() == 1
                    && declaringClass.equals(constructor.getParameterTypes()[0])) {
                creatorConstructor = constructor;
                index = i;
                break;
            } else if (creatorConstructor == null) {
                creatorConstructor = constructor;
                index = i;
            } else if (constructor.getParameterCount() == 0) {
                creatorConstructor = constructor;
                index = i;
            } else if (creatorConstructor.getParameterCount() < constructor.getParameterCount()) {
                creatorConstructor = constructor;
                index = i;
            }
        }

        if (index != -1) {
            alternateConstructors.remove(index);
        }

        if (creatorConstructor != null && creatorConstructor.getParameterCount() != 0 && beanInfo.seeAlso == null) {
            boolean record = BeanUtils.isRecord(objectClass);

            creatorConstructor.setAccessible(true);
            String[] parameterNames = beanInfo.createParameterNames;
            if (record && parameterNames == null) {
                parameterNames = BeanUtils.getRecordFieldNames(objectClass);
            }

            if (parameterNames == null || parameterNames.length == 0) {
                parameterNames = ASMUtils.lookupParameterNames(creatorConstructor);

                Parameter[] parameters = creatorConstructor.getParameters();
                FieldInfo fieldInfo = new FieldInfo();
                for (int i = 0; i < parameters.length && i < parameterNames.length; i++) {
                    fieldInfo.init();

                    Parameter parameter = parameters[i];

                    provider.getFieldInfo(fieldInfo, objectClass, creatorConstructor, i, parameter);
                    if (fieldInfo.fieldName != null) {
                        parameterNames[i] = fieldInfo.fieldName;
                    }
                }
            }

            int matchCount = 0;
            if (defaultConstructor != null) {
                for (int i = 0; i < parameterNames.length; i++) {
                    String parameterName = parameterNames[i];
                    if (parameterName == null) {
                        continue;
                    }

                    for (int j = 0; j < fieldReaderArray.length; j++) {
                        FieldReader fieldReader = fieldReaderArray[j];
                        if (fieldReader != null) {
                            if (parameterName.equals(fieldReader.fieldName)) {
                                matchCount++;
                                break;
                            }
                        }
                    }
                }
            }

            if (!(fieldBased)
                    && !(Throwable.class.isAssignableFrom(objectClass))
                    && defaultConstructor == null
                    && matchCount != parameterNames.length) {
                if (creatorConstructor.getParameterCount() == 1) {
                    FieldInfo fieldInfo = new FieldInfo();
                    provider.getFieldInfo(fieldInfo, objectClass, creatorConstructor, 0, creatorConstructor.getParameters()[0]);
                    if (record) {
                        Field field = getField(objectClass, fieldInfo.fieldName);
                        if (field != null) {
                            provider.getFieldInfo(fieldInfo, objectClass, field);
                        }
                    }

                    if ((fieldInfo.features & FieldInfo.VALUE_MASK) != 0) {
                        Type valueType = creatorConstructor.getGenericParameterTypes()[0];
                        Class valueClass = creatorConstructor.getParameterTypes()[0];

                        JSONSchema jsonSchema = null;
                        if (fieldInfo.schema != null && !fieldInfo.schema.isEmpty()) {
                            JSONObject object = JSON.parseObject(fieldInfo.schema);
                            if (!object.isEmpty()) {
                                jsonSchema = JSONSchema.of(object, valueClass);
                            }
                        }

                        Object defaultValue = fieldInfo.defaultValue;
                        if (defaultValue != null && defaultValue.getClass() != valueClass) {
                            Function typeConvert = JSONFactory
                                    .getDefaultObjectReaderProvider()
                                    .getTypeConvert(defaultValue.getClass(), valueType);
                            if (typeConvert != null) {
                                defaultValue = typeConvert.apply(defaultValue);
                            } else {
                                throw new JSONException("illegal defaultValue : " + defaultValue + ", class " + valueClass.getName());
                            }
                        }

                        return new ObjectReaderImplValue(
                                objectClass,
                                valueType,
                                valueClass,
                                fieldInfo.features,
                                fieldInfo.format,
                                defaultValue,
                                jsonSchema,
                                creatorConstructor,
                                null,
                                null
                        );
                    }
                }

                if (allReadOnlyOrZero && fieldReaderArray.length != 0 && alternateConstructors.isEmpty()) {
                    for (int i = 0; i < parameterNames.length; i++) {
                        String paramName = parameterNames[i];
                        for (FieldReader fieldReader : fieldReaderArray) {
                            if (fieldReader.field != null
                                    && fieldReader.field.getName().equals(paramName)
                                    && !fieldReader.fieldName.equals(paramName)
                            ) {
                                parameterNames[i] = fieldReader.fieldName;
                                break;
                            }
                        }
                    }
                }

                Function function = null;
                BiFunction biFunction = null;
                if (JIT) {
                    if (creatorConstructor.getParameterCount() == 1) {
                        function = LambdaMiscCodec.createFunction(creatorConstructor);
                    } else if (creatorConstructor.getParameterCount() == 2) {
                        biFunction = LambdaMiscCodec.createBiFunction(creatorConstructor);
                    }
                }

                Function<Map<Long, Object>, T> constructorFunction = new ConstructorFunction(
                        alternateConstructors,
                        creatorConstructor,
                        function,
                        biFunction,
                        null,
                        parameterNames
                );

                FieldReader[] paramFieldReaders = createFieldReaders(
                        provider,
                        objectClass,
                        objectType,
                        creatorConstructor,
                        creatorConstructor.getParameters(),
                        parameterNames
                );
                return createNoneDefaultConstructorObjectReader(
                        objectClass,
                        beanInfo,
                        constructorFunction,
                        alternateConstructors,
                        parameterNames,
                        paramFieldReaders,
                        fieldReaderArray
                );
            }
        }

        if (beanInfo.seeAlso != null && beanInfo.seeAlso.length != 0) {
            return createObjectReaderSeeAlso(
                    objectClass,
                    beanInfo.typeKey,
                    beanInfo.seeAlso,
                    beanInfo.seeAlsoNames,
                    beanInfo.seeAlsoDefault,
                    fieldReaderArray
            );
        }

        if (objectClass.isInterface()) {
            return new ObjectReaderInterface(
                    objectClass,
                    null,
                    null,
                    0L,
                    null,
                    null,
                    fieldReaderArray
            );
        }

        Supplier<T> creator = createSupplier(objectClass);
        JSONSchema jsonSchema = JSONSchema.of(JSON.parseObject(beanInfo.schema), objectClass);
        ObjectReader<T> objectReader = createObjectReader(
                objectClass,
                beanInfo.typeKey,
                beanInfo.rootName,
                beanInfo.readerFeatures,
                jsonSchema,
                creator,
                null,
                fieldReaderArray);

        if (objectReader instanceof ObjectReaderBean) {
            JSONReader.AutoTypeBeforeHandler beforeHandler = null;
            if (beanInfo.autoTypeBeforeHandler != null) {
                try {
                    Constructor constructor = beanInfo.autoTypeBeforeHandler.getDeclaredConstructor();
                    constructor.setAccessible(true);
                    beforeHandler = (JSONReader.AutoTypeBeforeHandler) constructor.newInstance();
                } catch (Exception ignored) {
                    // ignored
                }
            }

            if (beforeHandler != null) {
                ((ObjectReaderBean<T>) objectReader).setAutoTypeBeforeHandler(beforeHandler);
            }
        }

        return objectReader;
    }