class ObjectReaderInterface<T>
        extends ObjectReaderAdapter<T> {
    public ObjectReaderInterface(
            Class objectClass,
            String typeKey,
            String typeName,
            long features,
            Supplier creator,
            Function buildFunction,
            FieldReader[] fieldReaders
    ) {
        super(objectClass, typeKey, typeName, features, null, creator, buildFunction, fieldReaders);
    }

    @Override
    public T readJSONBObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
        if (jsonReader.nextIfNull()) {
            return null;
        }

        ObjectReader autoTypeReader = jsonReader.checkAutoType(this.objectClass, this.typeNameHash, this.features | features);
        if (autoTypeReader != null && autoTypeReader.getObjectClass() != this.objectClass) {
            return (T) autoTypeReader.readJSONBObject(jsonReader, fieldType, fieldName, features);
        }

        if (jsonReader.isArray()) {
            if (jsonReader.isSupportBeanArray()) {
                return readArrayMappingJSONBObject(jsonReader, fieldType, fieldName, features);
            } else {
                throw new JSONException(jsonReader.info("expect object, but " + JSONB.typeName(jsonReader.getType())));
            }
        }

        boolean objectStart = jsonReader.nextIfObjectStart();

        JSONObject jsonObject = new JSONObject();
        Object object;
        for (int i = 0; ; ++i) {
            if (jsonReader.nextIfObjectEnd()) {
                break;
            }

            long hash = jsonReader.readFieldNameHashCode();
            if (hash == typeKeyHashCode && i == 0) {
                long typeHash = jsonReader.readValueHashCode();
                JSONReader.Context context = jsonReader.getContext();
                ObjectReader autoTypeObjectReader = autoType(context, typeHash);
                if (autoTypeObjectReader == null) {
                    String typeName = jsonReader.getString();
                    autoTypeObjectReader = context.getObjectReaderAutoType(typeName, null);

                    if (autoTypeObjectReader == null) {
                        throw new JSONException(jsonReader.info("auotype not support : " + typeName));
                    }
                }

                if (autoTypeObjectReader == this) {
                    continue;
                }

                jsonReader.setTypeRedirect(true);
                return (T) autoTypeObjectReader.readJSONBObject(jsonReader, fieldType, fieldName, features);
            }

            if (hash == 0) {
                continue;
            }

            FieldReader fieldReader = getFieldReader(hash);
            if (fieldReader == null && jsonReader.isSupportSmartMatch(features | this.features)) {
                long nameHashCodeLCase = jsonReader.getNameHashCodeLCase();
                fieldReader = getFieldReaderLCase(nameHashCodeLCase);
            }
            if (fieldReader == null) {
                jsonObject.put(jsonReader.getFieldName(), jsonReader.readAny());
            } else {
                Object fieldValue = fieldReader.readFieldValue(jsonReader);
                jsonObject.put(fieldReader.fieldName, fieldValue);
            }
        }

        object = TypeUtils.newProxyInstance(objectClass, jsonObject);
        if (schema != null) {
            schema.assertValidate(object);
        }

        return (T) object;
    }

    @Override
    public T readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
        if (jsonReader.jsonb) {
            return readJSONBObject(jsonReader, fieldType, fieldName, features);
        }

        if (jsonReader.nextIfNull()) {
            jsonReader.nextIfComma();
            return null;
        }

        if (jsonReader.isArray() && jsonReader.isSupportBeanArray(getFeatures() | features)) {
            return readArrayMappingObject(jsonReader, fieldType, fieldName, features);
        }

        T object;
        JSONObject jsonObject = new JSONObject();
        boolean objectStart = jsonReader.nextIfObjectStart();
        if (!objectStart) {
            char ch = jsonReader.current();
            // skip for fastjson 1.x compatible
            if (ch == 't' || ch == 'f') {
                jsonReader.readBoolValue(); // skip
                return null;
            }

            if (ch != '"' && ch != '\'' && ch != '}') {
                throw new JSONException(jsonReader.info());
            }
        }

        for (int i = 0; ; i++) {
            if (jsonReader.nextIfObjectEnd()) {
                break;
            }

            JSONReader.Context context = jsonReader.getContext();
            long features3, hash = jsonReader.readFieldNameHashCode();
            JSONReader.AutoTypeBeforeHandler autoTypeFilter = context.getContextAutoTypeBeforeHandler();
            if (i == 0
                    && hash == getTypeKeyHash()
                    && ((((features3 = (features | getFeatures() | context.getFeatures())) & JSONReader.Feature.SupportAutoType.mask) != 0) || autoTypeFilter != null)
            ) {
                ObjectReader reader = null;

                long typeHash = jsonReader.readTypeHashCode();
                if (autoTypeFilter != null) {
                    Class<?> filterClass = autoTypeFilter.apply(typeHash, objectClass, features3);
                    if (filterClass == null) {
                        filterClass = autoTypeFilter.apply(jsonReader.getString(), objectClass, features3);
                        if (filterClass != null) {
                            reader = context.getObjectReader(filterClass);
                        }
                    }
                }

                if (reader == null) {
                    reader = autoType(context, typeHash);
                }

                String typeName = null;
                if (reader == null) {
                    typeName = jsonReader.getString();
                    reader = context.getObjectReaderAutoType(
                            typeName, objectClass, features3
                    );

                    if (reader == null) {
                        throw new JSONException(jsonReader.info("No suitable ObjectReader found for" + typeName));
                    }
                }

                if (reader == this) {
                    continue;
                }

                FieldReader fieldReader = reader.getFieldReader(hash);
                if (fieldReader != null && typeName == null) {
                    typeName = jsonReader.getString();
                }

                object = (T) reader.readObject(
                        jsonReader, null, null, features | getFeatures()
                );

                if (fieldReader != null) {
                    fieldReader.accept(object, typeName);
                }

                return object;
            }

            FieldReader fieldReader = getFieldReader(hash);
            if (fieldReader == null && jsonReader.isSupportSmartMatch(features | getFeatures())) {
                long nameHashCodeLCase = jsonReader.getNameHashCodeLCase();
                fieldReader = getFieldReaderLCase(nameHashCodeLCase);
            }

            if (fieldReader == null) {
                jsonObject.put(jsonReader.getFieldName(), jsonReader.readAny());
            } else {
                Object fieldValue = fieldReader.readFieldValue(jsonReader);
                jsonObject.put(fieldReader.fieldName, fieldValue);
            }
        }

        jsonReader.nextIfComma();

        object = (T) TypeUtils.newProxyInstance(objectClass, jsonObject);
        Function buildFunction = getBuildFunction();
        if (buildFunction != null) {
            object = (T) buildFunction.apply(object);
        }

        if (schema != null) {
            schema.assertValidate(object);
        }

        return object;
    }

    @Override
    public T createInstance(long features) {
        JSONObject object = new JSONObject();
        return (T) TypeUtils.newProxyInstance(objectClass, object);
    }

    @Override
    public T createInstance(Map map, long features) {<FILL_FUNCTION_BODY>}
}

        JSONObject object;
        if (map instanceof JSONObject) {
            object = (JSONObject) map;
        } else {
            object = new JSONObject(map);
        }
        return (T) TypeUtils.newProxyInstance(objectClass, object);
    
<methods>public transient void <init>(Class#RAW, Supplier<T>, FieldReader#RAW[]) ,public transient void <init>(Class#RAW, java.lang.String, java.lang.String, long, com.alibaba.fastjson2.schema.JSONSchema, Supplier<T>, Function#RAW, FieldReader#RAW[]) ,public transient void <init>(Class#RAW, java.lang.String, java.lang.String, long, Supplier<T>, Function#RAW, FieldReader#RAW[]) ,public transient void <init>(Class#RAW, java.lang.String, java.lang.String, long, com.alibaba.fastjson2.schema.JSONSchema, Supplier<T>, Function#RAW, Class#RAW[], java.lang.String[], FieldReader#RAW[]) ,public transient void <init>(Class#RAW, java.lang.String, java.lang.String, long, com.alibaba.fastjson2.schema.JSONSchema, Supplier<T>, Function#RAW, Class#RAW[], java.lang.String[], Class#RAW, FieldReader#RAW[]) ,public void apply(Consumer<FieldReader#RAW>) ,public java.lang.Object auoType(com.alibaba.fastjson2.JSONReader, Class#RAW, long) ,public ObjectReader#RAW autoType(com.alibaba.fastjson2.reader.ObjectReaderProvider, long) ,public ObjectReader#RAW autoType(com.alibaba.fastjson2.JSONReader.Context, long) ,public T createInstance(Collection#RAW) ,public T createInstance(long) ,public T createInstance(Map#RAW, long) ,public final Function#RAW getBuildFunction() ,public final long getFeatures() ,public int getFieldOrdinal(long) ,public FieldReader#RAW getFieldReader(long) ,public FieldReader#RAW getFieldReaderLCase(long) ,public FieldReader#RAW[] getFieldReaders() ,public final java.lang.String getTypeKey() ,public final long getTypeKeyHash() ,public T readArrayMappingJSONBObject(com.alibaba.fastjson2.JSONReader, java.lang.reflect.Type, java.lang.Object, long) ,public T readArrayMappingObject(com.alibaba.fastjson2.JSONReader, java.lang.reflect.Type, java.lang.Object, long) ,public T readJSONBObject(com.alibaba.fastjson2.JSONReader, java.lang.reflect.Type, java.lang.Object, long) <variables>final non-sealed Constructor#RAW constructor,protected final non-sealed FieldReader#RAW[] fieldReaders,final non-sealed long[] hashCodes,final non-sealed long[] hashCodesLCase,volatile boolean instantiationError,final non-sealed short[] mapping,final non-sealed short[] mappingLCase,final non-sealed Class#RAW[] seeAlso,final non-sealed Class#RAW seeAlsoDefault,final non-sealed Map<java.lang.Long,Class#RAW> seeAlsoMapping,final non-sealed java.lang.String[] seeAlsoNames,protected final non-sealed java.lang.String typeKey,protected final non-sealed long typeKeyHashCode