freezed
freezed copied to clipboard
Use of custom converter in freezed class
Describe the bug
I have json responses like these and these need to be serialized to BlockId
Class.
{"block_hash": "0x3871c8a0c3555687515a07f365f6f5b1d8c2ae953f7844575b8bde2b2efed27"}
{"block_number": 1}
and
"block_tag"
These are the 3 types of responses that I want to deserialize. I don't have a problem with the first two. It's the 3rd one that is causing an issue. The BlockId for the 1st two will have respective attributes, but for the 3rd one, itself should be a String value.
This is my current code, but it's giving me wrong output. toJson
for the 3rd type should yield a String and not a JSON.
@freezed
class BlockId with _$BlockId {
const factory BlockId.blockHash({
required StarknetFieldElement blockHash,
}) = BlockIdHash;
const factory BlockId.blockNumber({
required int blockNumber,
}) = BlockIdNumber;
const factory BlockId.blockTag({
required String blockTag,
}) = BlockIdTag;
factory BlockId.fromJson(Map<String, dynamic> json) =>
_$BlockIdFromJson(json);
}
I came across documentation for using Converter
and I tried this
class BlockIdConverter implements JsonConverter<BlockId, dynamic> {
const BlockIdConverter();
// BlockId can be constructed from a Map as well as a String.
@override
BlockId fromJson(dynamic value) {
if (value is Map) {
Map<String, dynamic> json = value as Map<String, dynamic>;
// you need to find some condition to know which type it is. e.g. check the presence of some field in the json
if (json.containsKey('block_hash')) {
return BlockId.blockHash(blockHash: json['block_hash']);
} else if (json.containsKey('block_number')) {
return BlockId.blockNumber(blockNumber: json['block_number']);
}
} else if (value is String) {
return BlockId.blockTag(blockTag: value);
}
throw Exception('Could not determine the BlockId from given value: $json');
}
@override
dynamic toJson(BlockId data) {
return data.when<dynamic>(blockHash: (StarknetFieldElement blockHash) {
return <String, dynamic>{'block_hash': blockHash};
}, blockNumber: (int blockNumber) {
return <String, dynamic>{'block_number': blockNumber};
}, blockTag: (String blockTag) {
return blockTag;
});
}
}
It's still giving me error, when I try to perform this
BlockId blockId = valid_object;
json.encode(blockId)
It says that the toJson
method is missing from the object.
Expected behavior
I would expect the 3 different types of deserialized and serialized the same via the BlockId
class.
@rrousselGit Do you have any thoughts on this?
@rrousselGit Apologies for tagging. Would like to know if you could look into this!
My guess is that you need to enable explicit_to_json
for json_serializable
Cf the documentation:
Note: In order to serialize nested lists of freezed objects, you are supposed to either specify a @JsonSerializable(explicitToJson: true) or change explicit_to_json inside your build.yaml file (see the documentation).