mapToObject method

dynamic mapToObject(
  1. Type cls,
  2. Map<String, dynamic> map
)

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