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;
}