freezed
freezed copied to clipboard
Support deserializing unions with no "type" property but instead a different shape
Is your feature request related to a problem? Please describe. The API I'm using provides data like so:
{
"generalData": {}
"catInfo" {},
}
{
"generalData": {}
"dogInfo" {},
}
I have a freezed class for the generalData
, and several freezed union types for Info
.
At the moment, there's no way to choose an Info
type based on the key.
Describe the solution you'd like
Perhaps a JsonConverter
could be passed the key as well as the value?
Describe alternatives you've considered There are none (AFAIK).
Additional context
There's hardly a solution here.
I'd suggest manually writing your fromJson
/toJson
for such use-case.
Or ideally, modify the json to include a type
key:
{
"generalData": {}
"catInfo" {},
"type": "cat"
}
{
"generalData": {}
"dogInfo" {},
"type": "dog"
}
This should allow Freezed to deserialize such class, with:
@Freezed(unionKey: 'type')
class Animal with _$Animal {
factory Animal.cat(GeneralData generalData, CatInfo catInfo) = Cat;
factory Animal.dog(GeneralData generalData, Dog dogInfo) = Dog;
}
I'd suggest manually writing your fromJson/toJson for such use-case.
If I try to do that, the union fromJson
functions don't get generated.
Or ideally, modify the json to include a type key
Unfortunately, I don't control the API I'm using.
If I try to do that, the union fromJson functions don't get generated.
Yes, but that's expected.
This is perfect - thank you for the question and answer @rrousselGit @hacker1024
Looking back at this, it's probably reasonably doable by checking the Map's length and a bunch of json.containsKey(someKey)
It's fairly advanced and low priority for me though.
Would be a nice feature if you have to support third party APIs. Overall I think it's a bad API design which should be avoided in the first place..
You could do this on your own reasonably well with Dart 3
@Freezed(fromJson: true, toJson: true)
class Example with _$Example {
factory Example.a(int count) = ExampleA;
factory Example.b(String name) = ExampleB;
factory Example.fromJson(Map<String, Object?> json) {
return switch (json) {
{'count': int()} => ExampleA.fromJson(json),
{'name': String()} => ExampleB.fromJson(json),
_ => throw FormatException(),
};
}
}
Doing it automatically in Freezed sounds a bit error-prone because the order matters quite a bit in case of potential conflict. Even more so when considering nullable fields & such.
Although interesting, I have currently no plan to implement this. So I'll close this