【问题标题】:How to handle different JSON Responses from same source in flutter如何在颤动中处理来自同一来源的不同 JSON 响应
【发布时间】:2022-01-11 11:45:11
【问题描述】:

我有一个颤振应用程序在某个时候检索一个列表/或任何与此相关的内容,如果请求有任何问题,则会收到不同的响应。
例如:

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

失败:

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

使用quicktype.io,我创建了如下类:

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())),
      };
}

现在,问题是,在失败时,当我尝试调用 ResponseList responseAllFromJson(String str) =&gt; ResponseList.fromJson(json.decode(str)); 时出现异常,其中 exeption 显示为
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type 'String' is not a subtype of type 'List&lt;dynamic&gt;'

我希望有一个方法,首先检查状态,无论是成功还是失败,然后解析 json 的剩余部分(message)或解析整个 json 并返回适当的响应(失败时的文本和列表在成功的情况下对象)。
注意:我想要一个可重用的代码,这样我就可以将响应传递给该方法并从我的应用程序中的任何位置检索它。例如:

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

目前,上面会在失败时引发异常,但在成功时会顺利运行。

【问题讨论】:

  • CLASSNAME 只是将List&lt;dynamic&gt; 转换为适当的List&lt;CLASSNAME&gt;

标签: json flutter dart parsing json-api-response-converter


【解决方案1】:

你可以在解析时尝试这种方式。

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;
  }
}

然后这样称呼:

MainResponse mainResponse = MainResponse.fromJson(response);

还有这个:

 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 }');
    }

【讨论】:

  • 感谢您的回答,但这里有一个问题,我需要一个可用的方法,这意味着 Message 可以是任何取决于请求的东西,例如一个请求中的员工列表,或另一个请求中的项目列表,具有完全不同的属性。另外,稍微解释一下data['message'] = this.message.map((v) =&gt; v.toJson()).toList(); 如何能够提供Message 的列表。
  • @VAThomas :然后你必须检查每种类型,然后返回你想要的。为此: data['message'] = this.message.map((v) => v.toJson()).toList();将其映射消息从 Map 中列出。
  • 实现了第一部分,可重用代码...可以假设 data['message'] = this.message.map((v) =&gt; v.toJson()).toList();Message 类型无关吗?顺便说一句,非常感谢。
  • @VAThomas :直到您在消息键中获得列表而不是字符串之前都可以。如果您获得另一种类型的数据,那么它会产生问题,因为我根据您当前的响应需求进行了解析。
猜你喜欢
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 2011-09-22
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 2011-10-14
  • 1970-01-01
相关资源
最近更新 更多