deserialize method

  1. @override
Object? deserialize(
  1. DartType targetType,
  2. String expression,
  3. TypeHelperContextWithConfig context,
  4. bool defaultProvided,
)
inherited

Returns Dart code that deserializes an expression representing a JSON literal to into targetType.

If targetType is not supported, returns null.

Let's say you want to deserialize a class Foo by taking an int stored in a JSON literal and calling the Foo.fromInt constructor.

Treating expression as a opaque Dart expression representing a JSON literal, the deserialize implementation could be a simple as:

String deserialize(DartType targetType, String expression) =>
  "new Foo.fromInt($expression)";
```.

Note that [targetType] is not used here. If you wanted to support many
types of [targetType] you could write:

```dart
String deserialize(DartType targetType, String expression) =>
  "new ${targetType.name}.fromInt($expression)";
```.

Implementation

@override
Object? deserialize(DartType targetType, String expression,
    TypeHelperContextWithConfig context, bool defaultProvided) {
  if (!typeChecker.isExactlyType(targetType)) {
    return null;
  }
  final typeArgs = targetType.typeArgumentsOf(typeChecker)!;
  assert(typeArgs.length == 2);
  final keyArg = typeArgs.first;
  final valueArg = typeArgs.last;
  final keyArgAsGenericString =
      keyArg.getDisplayString(withNullability: true);
  final valueArgAsGenericString =
      valueArg.getDisplayString(withNullability: true);

  checkSafeKeyType(expression, keyArg);

  final valueArgIsAny = valueArg.isLikeDynamic;
  final keyStringable = isKeyStringable(keyArg);
  final targetTypeIsNullable = targetType.isNullableType || defaultProvided;
  final anyMap = context.config.anyMap;
  final optionalQuestion = targetTypeIsNullable ? '?' : '';

  if (!keyStringable) {
    if (valueArgIsAny) {
      if (anyMap) {
        if (keyArg.isLikeDynamic) {
          return wrapNullableIfNecessary(
              expression,
              deserializeFromMapExpression(
                  '($expression as Map$optionalQuestion)', keyArg, valueArg),
              targetTypeIsNullable);
        }
      } else {
        // this is the trivial case. Do a runtime cast to the known type of JSON
        // map values - `Map<String, dynamic>`
        return wrapNullableIfNecessary(
            expression,
            deserializeFromMapExpression(
                '($expression as Map<String, dynamic>)', keyArg, valueArg),
            targetTypeIsNullable);
      }
    }

    if (!targetTypeIsNullable &&
        (valueArgIsAny ||
            simpleJsonTypeChecker.isAssignableFromType(valueArg))) {
      // No mapping of the values or null check required!
      return wrapNullableIfNecessary(
          expression,
          deserializeFromMapExpression(
              'Map<String, $valueArgAsGenericString>.from($expression as Map)',
              keyArg,
              valueArg),
          targetTypeIsNullable);
    }
  }

  // In this case, we're going to create a new Map with matching reified
  // types.

  var itemSubVal = context.deserialize(valueArg, closureArg).toString();

  itemSubVal = wrapNullableIfNecessary(closureArg, itemSubVal, valueArg.isNullableType);


  final mapCast = anyMap ? 'as Map' : 'as Map<String, dynamic>';

  String keyUsage;
  if (keyArg.isEnum) {
    keyUsage = context.deserialize(keyArg, _keyParam).toString();
  } else if (context.config.anyMap &&
      !(keyArg.isDartCoreObject || keyArg.isDynamic)) {
    keyUsage = '$_keyParam as String';
  } else if (context.config.anyMap &&
      keyArg.isDartCoreObject &&
      !keyArg.isNullableType) {
    keyUsage = '$_keyParam as Object';
  } else {
    keyUsage = _keyParam;
  }

  final toFromString = forType(keyArg);
  if (toFromString != null) {
    keyUsage = toFromString.deserialize(keyArg, keyUsage, false, true)!;
  }

  return wrapNullableIfNecessary(
      expression,
      deserializeFromMapExpression(
          '($expression $mapCast).map('
          '($keyParam, $closureArg) => MapEntry($keyUsage, $itemSubVal),)',
          keyArg,
          valueArg),
      targetTypeIsNullable);
}