deserialize method

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

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,
) {
  final memberContent = enumValueMapFromType(targetType);

  if (memberContent == null) {
    return null;
  }

  final isMapKey = expression == keyParam;
  final jsonKey = jsonKeyForField(context.fieldElement, context.config);
  final unknownEnumValue = isMapKey ? null : jsonKey.unknownEnumValue;

  if (!targetType.isNullableType &&
      unknownEnumValue == jsonKeyNullForUndefinedEnumValueFieldName) {
    // If the target is not nullable,
    throw InvalidGenerationSourceError(
      '`$jsonKeyNullForUndefinedEnumValueFieldName` cannot be used with '
      '`JsonKey.unknownEnumValue` unless the field is nullable.',
      element: context.fieldElement,
    );
  }

  if (isMapKey) {
    final encodedValues = enumEncodedValues(targetType);
    if (encodedValues != null && encodedValues.any((v) => v is int)) {
      final keyString = context.config.anyMap
          ? '$expression as String'
          : expression;
      if (encodedValues.every((v) => v is int || v == null)) {
        expression = 'int.parse($keyString)';
      } else {
        expression = 'int.tryParse($keyString) ?? $keyString';
      }
    }
  }

  final nullEnumValue = enumValueForNull(targetType);

  String functionName;
  if (targetType.isNullableType || defaultProvided || nullEnumValue != null) {
    functionName = r'$enumDecodeNullable';
  } else {
    functionName = r'$enumDecode';
  }

  context.addMember(memberContent);

  final args = [
    constMapName(targetType),
    expression,
    if (unknownEnumValue != null) 'unknownValue: $unknownEnumValue',
  ];

  final decoded = '$functionName(${args.join(', ')})';
  if (!targetType.isNullableType && nullEnumValue != null) {
    final withNullEnum = '$decoded ?? $nullEnumValue';
    if (defaultProvided) {
      return DefaultContainer(
        expression,
        withNullEnum,
        checkKeyPresence: true,
      );
    }
    return withNullEnum;
  }
  return decoded;
}