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

fromJson cast error with nested Freezed Classes #1118

Closed
WesselvanDam opened this issue Aug 12, 2024 · 3 comments
Closed

fromJson cast error with nested Freezed Classes #1118

WesselvanDam opened this issue Aug 12, 2024 · 3 comments
Assignees
Labels
bug Something isn't working needs triage

Comments

@WesselvanDam
Copy link

Describe the bug
I get the following error:

Error: type '_Map<Object?, Object?>' is not a subtype of type 'Map<String, dynamic>' in type cast

Because I have a freezed class that has another freezed class as one of its fields, and the generated code does not correctly cast the JSON field of the parent class's fromJSON.

To Reproduce

Simplified code:

The parent class, UserModel:

@freezed
class UserModel with _$UserModel {
  @JsonSerializable(explicitToJson: true)
  const factory UserModel({
    @Default(CustomClaimsModel()) CustomClaimsModel customClaims,
  }) = _UserModel;
  const UserModel._();

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

child class, CustomClaimsModel:

@freezed
class CustomClaimsModel with _$CustomClaimsModel {
  @JsonSerializable(explicitToJson: true)
  const factory CustomClaimsModel({
    @Default(false) bool admin,
  }) = _CustomClaimsModel;

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

Expected behavior
I expect the parent class UserModel to be able to generate an instance of CustomClaimsModel using its fromJson method, which should use the CustomClaimsModel's fromJson method for the value of the field customClaims. If I change all references of Map<String, dynamic> in the code of CustomClaimsModel and its generated files to Map, the code works and I do not get the error. Hence, I suspect that the casting of the JSON to the Map is faulty. Let me know if I'm missing something!

@WesselvanDam
Copy link
Author

I am not sure what I had originally done in my project, but I tried to make it work again and the models are constructed without issue. Perhaps I messed up the syntax. Closing this one.

@WesselvanDam
Copy link
Author

A small update: I encountered the issue again: it turned out that it was only a problem that occurred on mobile, and not on web. I was testing on mobile for a while when I encountered this and filed the issue, then I re-implemented it when I was testing on web and I thought it was solved. Then I reverted back to mobile and the issue was back.

The root cause turns out to be firebase/flutterfire#11872, where it is written that the response of the cloud function that I use to fetch the required data is different depending on the platform. You don't notice it if you do not have nested classes: you just type myJson = Map<String, dynamic>.from(response.data as Map);

However, with nested freezed classes, this conversion is not sufficient, because the nested object will throw the ERROR: type '_Map<Object?, Object?>' is not a subtype of type 'Map<String, dynamic>' in type cast. It is necessary to cast the nested field beforehand as well. I have done this with this function:

  Map<String, dynamic> prepareJson(Map json) {
    final mappedJson = Map<String, dynamic>.from(json);
    // also map the nested field
    mappedJson['customClaims'] = json['customClaims'] != null
        ? Map<String, dynamic>.from(json['customClaims'] as Map)
        : null;
    return mappedJson;
  }

@jimmyff
Copy link

jimmyff commented Sep 5, 2024

@WesselvanDam see the readme, you need to use explicitToJson:

@freezed
class Example with _$Example {
  @JsonSerializable(explicitToJson: true)
  factory Example(@JsonKey(name: 'my_property') SomeOtherClass myProperty) = _Example;

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs triage
Projects
None yet
Development

No branches or pull requests

3 participants