How to map dynamic json api responses in dart

103

Team.fromJson takes a Map<String, dynamic> as a parameters but you give it a List<Map<String, dynamic>>.

I think what you want is to change the first expression you gave to:

ApiResponse<Team>.fromJson(
  json.decode(response.body),
  (data) => data.map((teamJson) => Team.fromJson(teamJson)),
)

Also you could type safe your factory be using:

class ApiResponse<T> {
  int status;
  String? message;
  T data;

  ApiResponse({
    required this.status,
    this.message,
    required this.data,
  });

  factory ApiResponse.fromJson(
    Map<String, dynamic> json,
    T Function(List<Map<String, dynamic>>) create,
  ) {
    return ApiResponse<T>(
      status: json['status'],
      message: json['message'],
      data: create(json['data']),
    );
  }
}

If you do so you will also have to change your first expression again to write the right type (I think you made a mistake but maybe I'm wrong):

ApiResponse<List<Team>>.fromJson(
  json.decode(response.body),
  (data) => data.map((teamJson) => Team.fromJson(teamJson)).toList(),
);
Share:
103
theEUG
Author by

theEUG

Updated on January 01, 2023

Comments

  • theEUG
    theEUG over 1 year

    I have an API response payload with dynamic data in the body. The API returns a list of objects in the data tag. I am trying to map the response to the appropriate model at runtime, however, I get an error message when doing so. How do I map the dynamic response objects at runtime without explicitly creating an API response model for each? Ideally the solution should be able to determine the target model the response object should be mapped to at runtime.

    I get the following error with my code: The argument type 'List<Map<String, dynamic>>' can't be assigned to the parameter type 'Map<String, dynamic>'.

    Following my attempt:

    return ApiResponse<Team>.fromJson(json.decode(response.body), (data) => Team.fromJson(data) as List<Map<String, dynamic>>);
    
    // Maps the API response to object
    class ApiResponse<T> {
      int status;
      String? message;
      T data;
    
      ApiResponse({
        required this.status,
        this.message,
        required this.data,
      });
    
      factory ApiResponse.fromJson(Map<String, dynamic> json, Function(List<Map<String, dynamic>>) create) {
        return ApiResponse<T>(
          status: json['status'],
          message: json['message'],
          data: create(json['data']),
        );
      }
    }
    

    My models

    
    class User{
      int? id;
      String? name;
      String? description;
      DateTime? createdAt;
      DateTime? updatedAt;
    
      User({
        this.id,
        this.name,
        this.description,
        this.createdAt,
        this.updatedAt
      });
    
      factory User.fromJson(Map<String, dynamic> json){
        return User(
          id: json['id'],
          name: json['name'],
          description: json['description'],
          createdAt: DateTime.parse(json['created_at']),
          updatedAt: DateTime.parse(json['updated_at']),
        );
      }
    }
    
    
    class Team {
      int id;
      String? name;
      String? region;
      DateTime? createdAt;
      DateTime? updatedAt;
    
      Team({
        required this.id,
        this.name,
        this.region,
        this.createdAt,
        this.updatedAt,
      });
    
      factory Team.fromJson(Map<String, dynamic> json){
        return Team(
          id: json['id'],
          name: json['name'],
          region: json['region'],
          createdAt: DateTime.parse(json['created_at']),
          updatedAt: DateTime.parse(json['updated_at']),
        );
      }
    }
    

    API response

    
    {
      "status": 200,
      "message": "Returned",
      "data": [
        {
          "id": 1,
          "name": "Trevo Mgino",
          "description": "A Description",
          "created_at": "2021-09-29T06:47:03.000000Z",
          "updated_at": "2021-09-29T06:47:03.000000Z"
        }
      ],
    }
    
    {
      "status": 200,
      "message": "Activated",
      "data": [
        {
          "id": 1,
          "name": "Team A",
          "region": "Region 1",
          "created_at": "2021-09-29T06:47:03.000000Z",
          "updated_at": "2021-09-29T06:47:03.000000Z"
        },
        {
          "id": 2,
          "name": "Team B",
          "region": "Region 1",
          "created_at": "2021-09-29T06:47:03.000000Z",
          "updated_at": "2021-09-29T06:47:03.000000Z"
        }
      ],
    }
    
    • Muhammad Arbaz Zafar
      Muhammad Arbaz Zafar over 2 years
      just decode your json and pass this json team.formjson(json)