Search code examples
flutterdartgenericsfreezedflutter-freezed

Deserialising using Freezed with Generic Type Class


Feature for deserializing Generic Classes was introduced to freeze a few months back.

I am trying to follow the documentation, but I am facing a compile time error:

The argument type 'NameOfClass Function(Map<String, dynamic>)' can't be assigned to the parameter type 'NameOfClass Function(Object?)'.

Here is a simplified version of my data classes to explain what I am trying to achieve.

1. Outer Class

@Freezed(genericArgumentFactories: true)
class ResponseWrapper<T> with _$ResponseWrapper<T>{
  const factory ResponseWrapper ({
    final String? Status,
    final T? Response,
  }) = _ResponseWrapper;

  factory ResponseWrapper.fromJson(Map<String, dynamic> json,
      T Function(Object? json) fromJsonT)
    => _$ResponseWrapperFromJson<T>(json, fromJsonT);
}

2. Inner Class

@freezed
class NewUser with _$NewUser {
  const factory NewUser({
    String? firstName,
    String? middleName,
    String? surname,
    String? username,
    String? emailId,
  }) = _NewUser;

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

Running the command flutter pub run build_runner build runs without any errors and all the red squiggly lines disappear.

3. Attempting to deserialize

I am using the following code to deserialize the json.

const String stringResponse = '{"Status": "Success", "Response": { "firstName": "XYZ", "middleName": "ABC", "surname": "EDF", "username": "abc", "emailId": "[email protected]" } }';

final Map<String, dynamic> encoded = jsonDecode(stringResponse);
final ResponseWrapper<NewUser> newUserWithWrapper = ResponseWrapper.fromJson(encoded, NewUser.fromJson);

In the above code block, on the last line's NewUser.fromJson I am getting red squiggly line error that says: The argument type 'NewUser Function(Map<String, dynamic>)' can't be assigned to the parameter type 'NewUser Function(Object?)'.


Solution

  • Although I am not sure if it is a better approach, changing the last line to the following solves the problem:

    final ResponseWrapper<NewUser> newUserWithWrapper = ResponseWrapper.fromJson(
          encoded,
          (Object? json) => NewUser.fromJson(json as Map<String, dynamic>));