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