flutterdartjsonserializerjson-annotation

How to have dynamic multitype value in Dart/Flutter when using @JsonSerializable()?


I am using Flutter with json_annotation library and have one data class that is used to represent json response coming from one api.

import 'package:json_annotation/json_annotation.dart';
import 'package:app/dtos/user.dart';
import 'package:app/dtos/limited_user.dart';


part 'pending_project.g.dart';

@JsonSerializable()
class PendingProject {
  @JsonKey(name: "user")
  final User|LimitedUser user; // here I might have sometimes returned User type other types LimitedUser

  @JsonKey(name: "updatedAt")
  final String updatedAt;

  PendingProject(this.user, this.updatedAt);

  factory PendingProject.fromJson(Map<String, dynamic> json) =>
      _$PendingProjectFromJson(json);

  Map<String, dynamic> toJson() => _$PendingProjectToJson(this);
}

The api returns different values for user field based on some logic. Sometimes objects of type User other types of type LimitedUser

I have both those objects defined but cannot make it work in the json schema above.

How can I leave user object as dynamic maybe or json string and further parse manually in code or some other solution

Both User and LimitedUser have one common field named type that allows us to differentiate what we got back.

for User, type="user"

for LimitedUser, type="limitedUser"

all the other fields can be different we cannot assume anything else

PS: pending_project.g.dart is auto generated file with the library itself by running flutter packages pub run build_runner build


Solution

  • I solved this by using fromJson as below

    @JsonKey(name: "user", fromJson: mapUser)
    final Object user;
    
    
    /// other code
    
    Object mapUser(Map<String, dynamic> value)  {
      if (value['type'] == 'user') {
        User.fromJson(value);
      }
    
      return LimitedUser.fromJson(value);
    }
    
    

    The other code in ui is checking:

    if (obj is User) {
      return somewidgetforuser(obj);
    }
    return somewidgedforlimiteduser(obj);