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

Generate null checking code if the property is nullable when using `@JsonKey(fromJson)`

Open hurelhuyag opened this issue 2 years ago • 2 comments

Let's consider this example.

@JsonSerializable()
class Product {

  @JsonKey(fromJson: ProductType.byId)
  final ProductType? type;

  const Product({required this.type});

}

Currently when I run build_runner. The generated code will look like this.

Product _$PFromJson(Map<String, dynamic> json) => Product(
      type: ProductType.byId(json['type'] as String),
    );

I'm suggesting if the property is nullable, then the generator can set a null value for the type property.

Product _$PFromJson(Map<String, dynamic> json) => Product(
      type: json['type'] == null ? null : ProductType.byId(json['type'] as String),
    );

hurelhuyag avatar Sep 19 '23 09:09 hurelhuyag

I am not sure if this counts as a new bug, or just part of this one, but when attempting to work around this issue, the annotation @JsonKey(fromJson: foo, defaultValue: null) results in the generated code not having a null default either, so there is no quick work around for this issue that I can see.

ss23 avatar Jan 06 '24 06:01 ss23

Yes, I'm surprised this is not the default behavior.

We have some JSON objects that we have to parse in which we receive date fields as millisecondsSinceEpoch.

I can't to:

@JsonKey(fromJson: DateTime.fromMillisecondsSinceEpoch)
final DateTime? myDate;

Because DateTime.fromMillisecondsSinceEpoch returns a DateTime instead of a DateTime?. Because of this, I have to use a "helper" function:

@JsonKey(fromJson: parseDateTimeFromMilliseconds)
final DateTime? myDate;

// ...

DateTime? parseDateTimeFromMilliseconds(int? milliseconds) {
  if (milliseconds == null) {
	return null;
  } else {
	return DateTime.fromMillisecondsSinceEpoch(millisecond);
  }
}

This seems so unnecessary.

mateusfccp avatar Mar 24 '24 13:03 mateusfccp