createDeserializer method
Implementation
Mapper createDeserializer() {
Map<Type, MappingDefinition> mappings = {};
var queue = Queue<Type>.from([type]);
// local function
MappingDefinition process(Type type) {
var typeDescriptor = TypeDescriptor.forType(type);
var jsonSerializable = typeDescriptor.findAnnotation<JsonSerializable>() ?? JsonSerializable();
MappingDefinition typeMapping;
if (jsonSerializable.discriminatorField.isNotEmpty)
typeMapping = PolymorphicMappingDefinition(field: jsonSerializable.discriminatorField, targetClass: type);
else
typeMapping = MappingDefinition(sourceClass: Map<String, dynamic>, targetClass: type);
mappings[type] = typeMapping;
// local function
void check(Type type) {
if ( !TypeDescriptor.hasType(type))
return;
if (!mappings.containsKey(type)) {
queue.add(type);
// check all subclasses as well
for ( var sub in TypeDescriptor.forType(type).childClasses)
check(sub.type);
}
}
for ( var sub in TypeDescriptor.forType(type).childClasses)
check(sub.type);
// process fields
for ( var field in typeDescriptor.getFields()) {
var json = field.findAnnotation<Json>() ?? Json(name: field.name, defaultValue: null);
var includeNull = jsonSerializable.includeNull && json.includeNull != false;
if ( json.ignore)
continue;
var jsonField = json.name;
if (jsonField.isEmpty)
jsonField = field.name;
Object? defaultValue = JSONAccessor;
if ( !json.required) {
defaultValue = json.defaultValue;
//if ( !field.type.isValid(defaultValue))
// throw MapperException("the default $defaultValue for ${field.name} is not valid"); // TODO?
}
if (field.type is ListType) {
var elementType = field.elementType;
check(elementType!);
typeMapping.map(
from: JSONAccessor(
name: jsonField,
type: List<dynamic>,
includeNull: includeNull,
defaultValue: defaultValue,
containerConstructor: () => []
),
to: field.name,
deep: true,
validate: validate
);
}
else if ( field.type is ObjectType) {
var objectType = field.type as ObjectType;
Convert? convert ;
if ( json.converter != null) {
convert = JSON.getConvert4(json.converter!);
}
else convert = JSON.instance.getConvert(field.type.type);
if ( !objectType.typeDescriptor.isEnum() && convert == null) {
var target = objectType.type;
check(target);
typeMapping.map(
from: JSONAccessor(
name: jsonField,
type: Map<String, dynamic>,
includeNull: includeNull,
defaultValue: defaultValue
),
//validate: validate,
to: field.name,
deep: true
);
}
else {
// manual converter?
typeMapping.map(
//convert: convert,
from: JSONAccessor(
name: jsonField,
type: field.type.type,
convert: convert?.targetConverter(),
includeNull: includeNull,
defaultValue: defaultValue,
),
to: field.name,
deep: convert == null,
validate: validate
);
}
} // if
else {
Convert? convert ;
if ( json.converter != null) {
convert = JSON.getConvert4(json.converter!);
}
else convert = JSON.instance.getConvert(field.type.type);
typeMapping.map(
from: JSONAccessor(
name: jsonField,
type: field.type.type,
convert: convert?.targetConverter(),
includeNull: includeNull,
defaultValue: defaultValue
),
to: field.name,
//convert: convert,
validate: validate
);
}
}
return typeMapping;
}
// work on queue
while (queue.isNotEmpty) {
process(queue.removeFirst());
}
// done
var mapper = Mapper(mappings.values.toList());
deserializerMapping = mapper.mappings.values.firstWhere((mapping) => mapping.typeDescriptor.type == type);
return mapper;
}