Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

includeIf #1114

Open
AlexanderFarkas opened this issue Mar 12, 2022 · 5 comments
Open

includeIf #1114

AlexanderFarkas opened this issue Mar 12, 2022 · 5 comments

Comments

@AlexanderFarkas
Copy link

AlexanderFarkas commented Mar 12, 2022

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.

@AlexanderFarkas AlexanderFarkas changed the title SkipSerializationIf includeIf Mar 12, 2022
@lutes1
Copy link

lutes1 commented Sep 11, 2023

Any news on that? Sounds like a no-brainer

@kevmoo
Copy link
Collaborator

kevmoo commented Sep 12, 2023

Would LOVE To see the suggested generated output for the input examples.

@AlexanderFarkas
Copy link
Author

AlexanderFarkas commented Sep 12, 2023

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"}

@AlexanderFarkas
Copy link
Author

Actually, having includeIfNull alternative applied BEFORE serialization would solve the problem.

@jointhejourney
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants