json_serializable.dart
json_serializable.dart copied to clipboard
includeIf
Is your feature request related to a problem? Please describe. PATCH REST requests, for example, are hard to do.
Photo's null
is meaningful. If we send photo == null
, then the photo should be deleted on the server and replaced by a placeholder.
Also, if we want to update only the name, photo should remain untouched.
@JsonSerializable(includeIfNull: false)
class PatchUser {
final String name;
final String? photo;
PatchUser(this.photo, this.name);
}
That wouldn't work, 'cause null
has meaning.
class Wrapper<T> {
final T value;
Wrapper(this.value);
T toJson() => value;
}
@JsonSerializable(includeIfNull: false)
class PatchUser {
final String name;
final String? photo;
PatchUser(this.photo, this.name);
}
That wouldn't also, because includeIfNull
applies after toJson is called.
Describe the solution you'd like
@JsonSerializable()
class PatchUser {
final String name;
@JsonKey(includeIf: _skipPhotoIf)
final Wrapper<String?>? photo;
PatchUser(this.photo, this.name);
}
bool _includeIf(Wrapper<String?>? value) => value != null;
Also for the whole thing:
@JsonSerializable(includeIf: _includeIf)
class PatchUser {
final Wrapper<String>? name;
final Wrapper<String?>? photo;
PatchUser(this.photo, this.name);
}
bool _includeIf(Object? value) => !(value is Wrapper && value == null);
Additional Context If this enhancement is welcome, I will be ready to make a PR.
Any news on that? Sounds like a no-brainer
Would LOVE To see the suggested generated output for the input examples.
Input:
class Optional<T extends Object?> {
final T? value;
Optional(this.value);
T? toJson() => value;
}
@JsonSerializable(includeIf: includeIf)
class PatchUser {
final Optional<String>? photoUrl;
final String? name;
PatchUser({required this.photoUrl, required this.name});
}
bool includeIf(Object? object) => object != null;
Output:
Map<String, dynamic> toJson() {
return {
if (includeIf(this.name)) "name": this.name,
if (includeIf(this.photoUrl)) "photoUrl": this.photoUrl.toJson(),
}
}
So, it's basically includeIfNull
, but it's applied BEFORE any toJson is called.
More examples:
final user = PatchUser(
photoUrl: null,
name: "Username",
);
print(user.toJson()); // {"name": "Username"}
final user = PatchUser(
photoUrl: Optional(null),
name: "Username",
);
print(user.toJson()); // {"photo": null, "name": "Username"}
Actually, having includeIfNull
alternative applied BEFORE serialization would solve the problem.
Absolutely great suggestion! Stumbled upon this issue while looking up for a way to properly support PATCH
requests that need a differentiation between an omitted field versus explicitly setting it to null
.