mapToObject method
Implementation
dynamic mapToObject(Type cls, Map<String, dynamic> map) {
final cm = reflectClass(cls);
final params = <Symbol, dynamic>{};
final listSeqs = <Symbol, MethodMirror>{};
final requiredParams = <Symbol>{};
final paramTypes = <Symbol, Type>{};
cm.declarations.forEach((key, value) {
if (value is MethodMirror && value.isConstructor) {
value.parameters.forEach((pm) {
if (pm.isNamed && pm.defaultValue!.reflectee == null) {
requiredParams.add(pm.simpleName);
}
paramTypes
.addEntries([MapEntry(pm.simpleName, pm.type.reflectedType)]);
});
}
});
cm.instanceMembers.forEach((Symbol key, MethodMirror value) {
if (value.isSynthetic && value.isGetter) {
final mapKey = nameUnderLine(symbolToName(key));
final fieldValue = map[mapKey];
if ([int, double, bool, String]
.contains(value.returnType.reflectedType)) {
if (map.containsKey(mapKey)) {
if (fieldValue != null) {
params[key] = fieldValue;
}
}
} else {
if (value.returnType.reflectedType.toString().startsWith('Map')) {
params[key] = fieldValue;
} else {
if (value.returnType.reflectedType.toString().startsWith('List')) {
listSeqs[key] = value;
} else {
if (map.containsKey(mapKey)) {
if (fieldValue != null) {
final objMap =
mapToObject(value.returnType.reflectedType, fieldValue);
params[key] = objMap;
}
}
}
}
}
}
});
requiredParams.forEach((pn) {
if (!params.containsKey(pn)) {
throw PropertyMissingException(
'Field<${nameUnderLine(symbolToName(pn))}> required but not provided');
}
});
params.forEach((key, value) {
if (paramTypes.containsKey(key)) {
if (value.runtimeType != paramTypes[key]) {
throw PropertyMissingException(
'Field<${nameUnderLine(symbolToName(key))}:${paramTypes[key]}> But ${value.runtimeType} provided');
}
}
});
final ins = cm.newInstance(const Symbol(''), [], params);
final returnObject = ins.reflectee;
listSeqs.forEach((Symbol key, MethodMirror value) {
final mapKey = nameUnderLine(symbolToName(key));
final fieldValue = map[mapKey];
final om = reflect(returnObject);
final listField = om.getField(key);
final subcm = value.returnType.typeArguments.first;
(fieldValue as List).forEach((ele) {
if ([int, double, bool, String].contains(subcm.reflectedType)) {
listField.delegate(Invocation.method(Symbol('add'), [ele]));
} else {
final subobj = mapToObject(subcm.reflectedType, ele);
listField.delegate(Invocation.method(Symbol('add'), [subobj]));
}
});
});
return returnObject;
}