json_serializable.dart icon indicating copy to clipboard operation
json_serializable.dart copied to clipboard

Arg `includeIfNull` is ignored when type is not nullable

Open mrgnhnt96 opened this issue 1 year ago • 0 comments

Flutter Version
Flutter 3.3.2 • channel stable • https://github.com/flutter/flutter.git
Framework • revision e3c29ec00c (6 days ago) • 2022-09-14 08:46:55 -0500
Engine • revision a4ff2c53d8
Tools • Dart 2.18.1 • DevTools 2.15.0

In my case, I have an enum with a null json value (to avoid a nullable type within my model class)

@JsonEnum()
enum BrandedType {
  @JsonValue(1)
  restaurant,
  @JsonValue(2)
  grocery,
  @JsonValue(null)
  unknown,
}

My Dart model class property:

@JsonKey(includeIfNull: false)
final BrandedType brandedType;

This is the generated code for this property

'branded_type': _$BrandedTypeEnumMap[instance.brandedType]!,
...
const _$BrandedTypeEnumMap = {
  BrandedType.restaurant: 1,
  BrandedType.grocery: 2,
  BrandedType.unknown: null,
};

And this is the json output for this property

"branded_type": null

What's happening in the generator is it's checking for a nullable type on the model class's property type. If the property is not a nullable type (as a Dart object), then it would seem redundant to generate the writeNotNull method because the value appears to not be nullable (as a serialized object).

This can be validated by making the property's type nullable

// --- model ---
@JsonKey(includeIfNull: false)
final BrandedType? brandedType;

// --- generated code ---
void writeNotNull(String key, dynamic value) {
    if (value != null) {
      val[key] = value;
    }
  }

writeNotNull('branded_type', _$BrandedTypeEnumMap[instance.brandedType]);
...
const _$BrandedTypeEnumMap = {
  BrandedType.restaurant: 1,
  BrandedType.grocery: 2,
  BrandedType.unknown: null,
};

Even when the dart object's value is set to BrandedType.unknown, there is no json output for this property when resolved with the _$BrandedTypeEnumMap value, because it resolves to null.

There is another possible outcome, instead of _$EnumMap[...] (where the key's value could return a null value), it would be property.toJson() (where toJson could return a null value). Since we are checking for the null value against the serialized property, and not the Dart model object's current value, the property's type isn't relevant.

A possible fix for this would be to ignore the nullable typing on the property of the Dart object, and generate the writeNotNull regardless.

mrgnhnt96 avatar Sep 20 '22 03:09 mrgnhnt96