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

@Default using static const and fromJson will generate code that does not compile #82

Closed
mono0926 opened this issue Mar 3, 2020 · 7 comments

Comments

@mono0926
Copy link
Contributor

mono0926 commented Mar 3, 2020

I've tested this at 0.9.1 , supported by #75.


As tested here, this works well:

@freezed
abstract class StaticConstDefault with _$StaticConstDefault {
  factory StaticConstDefault([@Default(Duration.zero) Duration value]) =
      _StaticConstDefault;
}

But, if fromJson line is added, it failed to compile.

@freezed
abstract class StaticConstDefault with _$StaticConstDefault {
  factory StaticConstDefault([@Default(Duration.zero) Duration value]) =
      _StaticConstDefault;
  // This failed to compile
  factory StaticConstDefault.fromJson(Map<String, dynamic> json) =>
      _$StaticConstDefaultFromJson(json);
}

Error log:

[SEVERE] json_serializable:json_serializable on x.dart:
Error running JsonSerializableGenerator
Error with `@JsonKey` on `value`. `defaultValue` is `Duration`, it must be a literal.
package:anycommu/model/entity/kpt/kpt.freezed.dart:45:18
   ╷
45 │   final Duration value;
   │                  ^^^^^
   ╵
@rrousselGit
Copy link
Owner

Duration is not serializable. You need to deserialize it into a timestamp

@rrousselGit
Copy link
Owner

Actually it doesn't sound to be related to if Duration is serializable or not (as no default value works).

It sounds like JsonKey just doesn't support Duration as a value. Maybe make an issue on json_serializable? I can't do anything about it.

@mono0926
Copy link
Contributor Author

mono0926 commented Mar 3, 2020

@rrousselGit

json_serializable supports Duration serialization(google/json_serializable.dart#336).

This is generated automatically and if @Default(Duration.zero) is omitted, everything works well.

_$_StaticConstDefault _$_$_StaticConstDefaultFromJson(
    Map<String, dynamic> json) {
  return _$_StaticConstDefault(
    json['value'] == null ? null : Duration(microseconds: json['value'] as int),
  );
}

Map<String, dynamic> _$_$_StaticConstDefaultToJson(
        _$_StaticConstDefault instance) =>
    <String, dynamic>{
      'value': instance.value?.inMicroseconds,
    };

It sounds like JsonKey just doesn't support Duration as a value. Maybe make an issue on json_serializable? I can't do anything about it.

Okay, thanks 👍
I'll investigate it a little more, and I might make an issue on json_serializable.

@rrousselGit
Copy link
Owner

In the mean time you could add an extra @JsonKey() next to the @Default.

But this means deserializing the json will not add the default value

@gysipos
Copy link

gysipos commented May 13, 2021

Just to add my experience with the issue: List of enums as @default value will cause the same error, for example:

    @Default([PoliKind.ESTATE]) 
    List<PoliKind> kinds, //always ESTATE

The enum:

  enum PoliKind {
    @JsonValue("AD")
    AD,
    @JsonValue("ESTATE")
    ESTATE
  }

the result:

Error with `@JsonKey` on `kinds`. `defaultValue` is `List > PoliKind`, it must be a literal.

@rrousselGit
Copy link
Owner

Unfortunately I don't think there's anything I can do here. It's json_serializable that is rejecting the default value.

But the @Default(...) @JsonKey() workaround seem to be enough. So I'll close this

@PiN73
Copy link

PiN73 commented May 6, 2022

Starting from freezed 2, this will work

@freezed
class Cart with _$Cart {
  const factory Cart({
    @Default([]) List<int> items,
  }) = _Cart;

  factory Cart.fromJson(Map<String, dynamic> json) => _$CartFromJson(json);
}

@freezed
class User with _$User {
  const factory User({
    @Default(Cart()) Cart cart,
  }) = _User;

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}

Then Cart.fromJson({}).items or User.fromJson({}).cart.items will give you []


Before freezed 2, use this workaround:

@Default(const Cart()) @JsonKey(fromJson: _CartFromNullableJson) Cart cart,
Cart _CartFromNullableJson(Map<String, dynamic>? json) =>
    json == null ? Cart() : Cart.fromJson(json);

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

No branches or pull requests

4 participants