Suppose I have a model class in freezed,
@freezed
abstract class Dto implements _$Dto {
const factory Dto({
String? name,
String? url,
}) = _Dto;
factory Dto.fromJson(Map<String, dynamic> json) =>
_$DtoFromJson(json);
}
Now, the json responses are,
1.
{
"name": "superuser root",
"display_picture_url": "/media_server/user.jpg"
}
{
"name": "superuser root",
"picture_url": "/media_server/user.jpg"
}
Without freezed, I write like this,
factory Dto.fromJson(Map<String, dynamic> json) => Dto(
name: json["name"],
value: json.containsKey('display_picture_url')
? json["display_picture_url"] :
json["picture_url"]
),
);
But in freezed, how can I achieve this?
I tried with JsonConverters, But I don't know how to deal with this scenario!
You can do this with readValue
parameter of @JsonKey
.
Excerpt from readValue
docs:
At times it's convenient to customize this behavior to support alternative names or to support logic that requires accessing multiple values at once.
Object? _urlReader(Map json, String key) {
if (key == 'picture_url') {
return json['picture_url'] ?? json['display_picture_url'];
}
return json[key];
}
@freezed
class Dto with _$Dto {
const factory Dto({
String? name,
@JsonKey(name: 'picture_url', readValue: _urlReader) String? url,
}) = _Dto;
factory Dto.fromJson(Map<String, dynamic> json) => _$DtoFromJson(json);
}
Future<void> testJson() async {
const json = """
[
{
"name": "Name 01",
"picture_url": "https://picture.url"
},
{
"name": "Name 02",
"display_picture_url": "https://display.picture.url"
}
]
""";
final decodedJson = jsonDecode(json) as List<dynamic>;
final models = decodedJson.map((e) {
return Dto.fromJson(e);
});
debugPrint("$models");
}
(Dto(name: Name 01, url: https://picture.url), Dto(name: Name 02, url: https://display.picture.url))