deserializeObject method

Object deserializeObject (
  1. dynamic jsonValue,
  2. DeserializationContext context
)

Implementation

Object deserializeObject(dynamic jsonValue, DeserializationContext context) {
  if (jsonValue == null) {
    return null;
  }
  var typeInfo = getTypeInfo(context.instanceType);
  final converter = getConverter(context.parentMeta, typeInfo.type);
  if (converter != null) {
    configureConverter(converter, deserializationContext: context);
    var convertedValue = converter.fromJSON(jsonValue, context.parentMeta);
    if (typeInfo.isIterable && jsonValue == convertedValue) {
      convertedValue = deserializeIterable(jsonValue, context);
    }
    return applyValueDecorator(convertedValue, typeInfo, context.parentMeta);
  }

  var convertedJsonValue;
  try {
    convertedJsonValue =
        (jsonValue is String) ? jsonDecoder.convert(jsonValue) : jsonValue;
  } on FormatException {
    throw MissingEnumValuesError(typeInfo.type);
  }

  if (typeInfo.isIterable ||
      (convertedJsonValue != null && convertedJsonValue is Iterable)) {
    return deserializeIterable(jsonValue, context);
  }

  if (convertedJsonValue is! Map<String, dynamic>) {
    return convertedJsonValue;
  }

  final jsonMap = JsonMap(convertedJsonValue);
  typeInfo =
      detectObjectType(null, context.instanceType, jsonMap, context.options);
  final cm = classes[typeInfo.typeName] ?? classes[typeInfo.genericTypeName];
  if (cm == null) {
    throw MissingAnnotationOnTypeError(typeInfo.type);
  }
  final classInfo = ClassInfo(cm);
  jsonMap.jsonMeta = classInfo.getMeta(context.options.scheme);

  final namedArguments = getNamedArguments(cm, jsonMap, context.options);
  final objectInstance = context.options.template ??
      (cm.isEnum
          ? null
          : cm.newInstance(
              classInfo
                  .getJsonConstructor(context.options.scheme)
                  .constructorName,
              getPositionalArguments(cm, jsonMap, context.options),
              namedArguments));
  final im = safeGetInstanceMirror(objectInstance);
  final mappedFields = namedArguments.keys
      .map((Symbol symbol) =>
          RegExp('"(.+)"').allMatches(symbol.toString()).first.group(1))
      .toList();

  enumeratePublicProperties(im, jsonMap, context.options, (name,
      jsonName,
      value,
      isGetterOnly,
      JsonProperty meta,
      converter,
      scalarType,
      TypeInfo typeInfo) {
    if (!jsonMap.hasProperty(jsonName)) {
      if (meta != null && meta.defaultValue != null && !isGetterOnly) {
        im.invokeSetter(name, meta.defaultValue);
      }
      return;
    }
    var fieldValue = jsonMap.getPropertyValue(jsonName);
    if (fieldValue is Iterable) {
      fieldValue = fieldValue
          .map((item) => deserializeObject(item,
              DeserializationContext(context.options, scalarType, meta)))
          .toList();
    } else {
      fieldValue = deserializeObject(fieldValue,
          DeserializationContext(context.options, typeInfo.type, meta));
    }
    if (converter != null) {
      final originalValue = im.invokeGetter(name);
      configureConverter(converter,
          value: originalValue ?? fieldValue,
          deserializationContext:
              DeserializationContext(context.options, typeInfo.type, meta));
      fieldValue = converter.fromJSON(fieldValue, meta);
    }
    if (!isGetterOnly) {
      fieldValue = applyValueDecorator(fieldValue, typeInfo, meta);
      im.invokeSetter(name, fieldValue);
      mappedFields.add(jsonName);
    }
  });

  final typeNameProperty =
      getTypeNameProperty(jsonMap.jsonMeta, context.options);
  final unmappedFields = jsonMap.map.keys
      .where((field) =>
          !mappedFields.contains(field) && field != typeNameProperty)
      .toList();
  if (unmappedFields.isNotEmpty) {
    final jsonAnySetter = classInfo.getJsonAnySetter(context.options.scheme);
    unmappedFields.forEach((field) {
      final jsonSetter =
          classInfo.getJsonSetter(field, context.options.scheme) ??
              jsonAnySetter;
      final params = jsonSetter == jsonAnySetter
          ? [field, jsonMap.map[field]]
          : [jsonMap.map[field]];
      if (jsonSetter != null) {
        im.invoke(jsonSetter.simpleName, params);
      }
    });
  }

  return applyValueDecorator(objectInstance, typeInfo, context.parentMeta);
}