0

I have a flutter application retrieving a list/or anything for that matter at some point, and if there's any issue with the request, a different response is received.
For Example:

{
  "status" : "success",
  "message":
    [
      {
        "updated_on" : "2022-01-09 14:26:07"
      }
    ]
}

For Failure:

{
  "status" : "error",
  "message" : "Query not found"
}

Using quicktype.io, I have created class as below:

class ResponseList {
  ResponseList({
    required this.status,
    required this.message,
  });

  String status;
  List<dynamic> message;

  factory ResponseList.fromJson(Map<String, dynamic> json) => ResponseList(
        status: json["status"],
        message: List<dynamic>.from(json["message"].map((x) => CLASSNAME.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "status": status,
        "message": List<dynamic>.from(message.map((x) => x.toJson())),
      };
}

Now, the problem is, on failure, this raises an exception when i try to call ResponseList responseAllFromJson(String str) => ResponseList.fromJson(json.decode(str)); where the exeption says
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type 'String' is not a subtype of type 'List<dynamic>'.

I want to have a method that checks the status first, whether success or failure and then parses the remaining of the json (in message) or parses the whole json and returns appropriate response (text in case of failure and list of objects in case of success).
Note: I want a reusable code, so that I can pass the response to the method and retrieve it from any point in my application. For example:

static bool responseStatus(dynamic response) {
    if (response != null) {
      if (responseListFromJson(response).status.trim().toLowerCase() == 'success') {
        return true;
      }
    }
    return false;
  }

Presently, above raises exception on failure but works smoothly on success.

vat69
  • 123
  • 1
  • 10

1 Answers1

0

You can try this way while parsing.

class MainResponse {
  String status;
  dynamic message;

  MainResponse({this.status, this.message});

  MainResponse.fromJson(Map<String, dynamic> json) {
    status = json['status'];
    if(json['message'] is String)  {

      message = json['message'];
    }else {

      message = <Message>[];
      json['message'].forEach((v) {
        message.add(new Message.fromJson(v));
      });

    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['status'] = this.status;
    if (this.message != null) {

      if(this.message is String) {
        data['message'] = this.message;
      }else {
        data['message'] = this.message.map((v) => v.toJson()).toList();
      }
    }
    return data;
  }
}

class Message {
  String updatedOn;

  Message({this.updatedOn});

  Message.fromJson(Map<String, dynamic> json) {
    updatedOn = json['updated_on'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['updated_on'] = this.updatedOn;
    return data;
  }
}

And call this way :

MainResponse mainResponse = MainResponse.fromJson(response);

and this :

 if(mainResponse.message is String) {
      var data = mainResponse.message as String;
      print('parsed String $data');
    }else {

      var list = mainResponse.message as List<Message>;
      print('parsed ${list[0].updatedOn }');
    }
Hardik Mehta
  • 2,195
  • 1
  • 11
  • 14
  • Thanks for the answer, but here is the catch, I need a usable method, means that `Message` can be anything depending upon the request, e.g. list of employees, in one request, or a list of items in another, having totally different properties. Also, a bit explanation on how `data['message'] = this.message.map((v) => v.toJson()).toList();` is able to provide a list of `Message`. – vat69 Jan 12 '22 at 07:15
  • @VAThomas : Then you have to check for every type and then return what you want. for this : data['message'] = this.message.map((v) => v.toJson()).toList(); its maping message to list from Map. – Hardik Mehta Jan 12 '22 at 08:22
  • Achieved the first part, reusable code... Is it ok to assume that `data['message'] = this.message.map((v) => v.toJson()).toList();` has nothing to do with the type `Message` ? BTW, thanks a ton. – vat69 Jan 12 '22 at 09:56
  • @VAThomas : its okay until until you get list in message key rather then string. if you get another type of data then its creates issue as i parsed as per your current response need. – Hardik Mehta Jan 12 '22 at 11:39