I'm trying to implement toJson/fromJson for a union generated by the freezed package. Let's say we have a class as following:
@freezed
abstract class Result with _$Result {
const factory Result.error(String message) = Error;
const factory Result.success() = Success;
factory Result.fromJson(Map<String, dynamic> json) => _$ResultFromJson(json);
}
Where I want to/fromJson to behave as following:
Result error = Result.error('some error');
expect(error.toJson(), {'type': 'error', 'message': 'some error'});
expect(Result.fromJson({'type': 'error', 'message': 'some error'}), error);
It's stated in the docs that you can use a JsonConverter
(fromJSON with multiple classes) but I don't know how to use it properly.
class ResultConverter implements JsonConverter<Result, Map<String, dynamic>> {
const ResultConverter();
@override
Result fromJson(Map<String, dynamic> json) {
if (json == null) {
return null;
}
switch (json['type'] as String) {
case 'success':
return Success.fromJson(json);
case 'error':
return Error.fromJson(json);
default:
throw FallThroughError();
}
}
@override
Map<String, dynamic> toJson(Result object) => object.map(
error: (e) => {'type': 'error', ...e.toJson()},
success: (s) => {'type': 'success', ...s.toJson()},
);
}
fromJson
works fine if the factory method calls ResultConverter().fromJson(this)
instead of the generated one, but that feels like a workaround and will not work on toJson.
Is it possible to annotate the Result class somehow so that the codegeneration will use the converter?
Yes, this resource has helped me - link to achieve it.
Plus, it works for dedicated named constructor in case of freezed
package.
Like this (please note no abstract
keyword and private
constructor added):
@freezed
class Result with _$Result {
const Result._();
@ResultConverter()
const factory Result.error(String message) = Error;
@ResultConverter()
const factory Result.success() = Success;
factory Result.fromJson(Map<String, dynamic> json) => _$ResultFromJson(json);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With