deserialize method
Object?
deserialize(
- DartType targetType,
- String expression,
- TypeHelperContextWithConfig context,
- 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,
) {
if (targetType is! InterfaceType) {
return null;
}
final classElement = targetType.element;
final fromJsonCtor = classElement.constructors
.singleWhereOrNull((ce) => ce.name == 'fromJson');
var output = expression;
if (fromJsonCtor != null) {
final positionalParams = fromJsonCtor.parameters
.where((element) => element.isPositional)
.toList();
if (positionalParams.isEmpty) {
throw InvalidGenerationSourceError(
'Expecting a `fromJson` constructor with exactly one positional '
'parameter. Found a constructor with 0 parameters.',
element: fromJsonCtor,
);
}
var asCastType = positionalParams.first.type;
if (asCastType is InterfaceType) {
final instantiated = _instantiate(asCastType, targetType);
if (instantiated != null) {
asCastType = instantiated;
}
}
output = context.deserialize(asCastType, output).toString();
final args = [
output,
..._helperParams(
context.deserialize,
_decodeHelper,
targetType,
positionalParams.skip(1),
fromJsonCtor,
),
];
output = args.join(', ');
} else if (_annotation(context.config, targetType)?.createFactory == true) {
if (context.config.anyMap) {
output += ' as Map';
} else {
output += ' as Map<String, dynamic>';
}
} else {
return null;
}
// TODO: the type could be imported from a library with a prefix!
// https://github.com/google/json_serializable.dart/issues/19
final lambda = LambdaResult(
output,
'${typeToCode(targetType.promoteNonNullable())}.fromJson',
);
return DefaultContainer(expression, lambda);
}