【问题标题】:How to convert Response JSON to Object in Flutter?如何在 Flutter 中将响应 JSON 转换为对象?
【发布时间】:2019-03-30 19:23:07
【问题描述】:

我正在尝试将成功的 JSON 字符串转换为 Object。可能是我没有以正确的方式做但是我有几个与将 JSON 转换为 Object 相关的问题。

我也在 Log 中得到了这个异常。

NoSuchMethodError: Class '**_InternalLinkedHashMap<String, dynamic>' has no instance method 'cast' with matching arguments**.<br>
Receiver: _LinkedHashMap len:3
**Tried calling: cast<Map<String, dynamic>>()**
  1. 我是否也需要在模型中转换该数据对象?
  2. 将 JSON 转换为对象 (SignUpResponse) 的最佳且简单的方法是什么。
  3. 最好用序列化?

响应 JSON:

{
    "data": {
        "_id": "5bd2a59f4c59de1ac517d7bf",
        "email": "fjhsd@gmail.com",
        "phoneNumber": "2417874147",
        "isAddressApproved": 0,
        "unitNumber": "144",
        "streetAddress": "sdfsddsf",
        "area": "asd",
        "zipCode": "112233",
        "totalOrder": 0,
        "todayOrder": 0,
        "isPauseDelivery": false,
        "vacationStartDt": null,
        "vacationEndDt": null,
        "defaultLiter": 1
    },
    "message": "New User Created",
    "error": false
}

由在线工具创建的SignUpResponse。

class SignUpResponse {
    Data data;
    String message;
    bool error;

    SignUpResponse({this.data, this.message, this.error});

    SignUpResponse.fromJson(Map<String, dynamic> json) {
    data = json['data'] != null ? new Data.fromJson(json['data']) : null;
    message = json['message'];
    error = json['error'];
    }

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

class Data {
    String sId;
    String email;
    String phoneNumber;
    int isAddressApproved;
    String unitNumber;
    String streetAddress;
    String area;
    String zipCode;
    int totalOrder;
    int todayOrder;
    bool isPauseDelivery;
    Null vacationStartDt;
    Null vacationEndDt;
    int defaultLiter;

    Data(
        {this.sId,
        this.email,
        this.phoneNumber,
        this.isAddressApproved,
        this.unitNumber,
        this.streetAddress,
        this.area,
        this.zipCode,
        this.totalOrder,
        this.todayOrder,
        this.isPauseDelivery,
        this.vacationStartDt,
        this.vacationEndDt,
        this.defaultLiter});

    Data.fromJson(Map<String, dynamic> json) {
    sId = json['_id'];
    email = json['email'];
    phoneNumber = json['phoneNumber'];
    isAddressApproved = json['isAddressApproved'];
    unitNumber = json['unitNumber'];
    streetAddress = json['streetAddress'];
    area = json['area'];
    zipCode = json['zipCode'];
    totalOrder = json['totalOrder'];
    todayOrder = json['todayOrder'];
    isPauseDelivery = json['isPauseDelivery'];
    vacationStartDt = json['vacationStartDt'];
    vacationEndDt = json['vacationEndDt'];
    defaultLiter = json['defaultLiter'];
    }

    Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['_id'] = this.sId;
    data['email'] = this.email;
    data['phoneNumber'] = this.phoneNumber;
    data['isAddressApproved'] = this.isAddressApproved;
    data['unitNumber'] = this.unitNumber;
    data['streetAddress'] = this.streetAddress;
    data['area'] = this.area;
    data['zipCode'] = this.zipCode;
    data['totalOrder'] = this.totalOrder;
    data['todayOrder'] = this.todayOrder;
    data['isPauseDelivery'] = this.isPauseDelivery;
    data['vacationStartDt'] = this.vacationStartDt;
    data['vacationEndDt'] = this.vacationEndDt;
    data['defaultLiter'] = this.defaultLiter;
    return data;
    }
}

调用 REST POST API

void postCallSignUp(BuildContext context, var body) {
// This Function will check Internet is available or not.
Utils.checkConnection().then((connectionResult) {
    if (connectionResult) {
    http.post(Constants.BASE_URL + Constants.CREATE_USER,
        body: body,
        headers: {
            "Accept": "application/json",
            "content-type": "application/json"
        }).then((http.Response response) {
        final String res = response.body;
        final int statusCode = response.statusCode;

        if (statusCode < 200 || statusCode > 400 || json == null) {
        _onFailureResponse(new Exception("Error while fetching data"));
        } else {
        //Parsing json response to particular Object.
        print(json.decode(res));

        // Unable to cast json here...
        final parsed = json.decode(res).cast<Map<String, dynamic>>();
        parsed.map<SignUpResponse>((json) => SignUpResponse.fromJson(json));
        SignUpResponse signUpResponse = parsed.map<SignUpResponse>((json) => SignUpResponse.fromJson(json));
        _onSuccessResponse(signUpResponse);
        }
    });
    } else {
    _onNoInternetConnection();
    Utils.showAlert(context, "Alert", "Internet is not connected.", () {
        Navigator.pop(context);
    });
    }
});
}

无法理解这里发生了什么?为什么我们必须做这么多来将我们的 json 转换为特定的对象?

【问题讨论】:

  • 使用这个; final Map 已解析 = json.decode(res);
  • 所以我们不需要投射 ?
  • 其实你只需要:final Map parsed = json.decode(res);
  • 以及如何将解析后的 json 转换为 SignUpResponse?
  • 我在下面添加了我的答案

标签: json http dart flutter


【解决方案1】:

不需要使用cast,可以直接解析成Map

final Map parsed = json.decode(res); 

拥有地图后,您可以使用该数据转换为您的对象。

final signUp = SignUpResponse.fromJson(parsed);

如果你想解析一个对象数组,你可以这样做:

//assuming this json returns an array of signupresponse objects
final List parsedList = json.decode(res); 

List<SignUpResponse> list = parsedList.map((val) =>  SignUpResponse.fromJson(val)).toList();

【讨论】:

  • 这很奇怪,而 list = json.decode(res).map((val) =&gt; SignUpResponse.fromJson(val)).toList(); 似乎失败了。
  • 也许你可以帮助解决这个问题。 stackoverflow.com/questions/61977195/…
【解决方案2】:

JSON:

    [
     {
       "id":1,
       "name":"Afghanistan",
       "iso3":"AFG",
       "iso2":"AF",
       "phone_code":"93",
       "capital":"Kabul",
       "currency":"AFN"
     },
     {
       "id":2,
       "name":"Aland Islands",
       "iso3":"ALA",
       "iso2":"AX",
       "phone_code":"+358-18",
       "capital":"Mariehamn",
       "currency":"EUR"
       },
    ]

POJO 类:

    class country{
       String id;
       String name;
       String currency;

       country({this.id,this.name,this.currency});

       factory country.fromJson(Map<String, dynamic> parsedJson){
         return country(
         id: parsedJson['id'].toString(),
         name : parsedJson['name'].toString(),
         currency: parsedJson['currency'].toString() 
         );
       }
    }

API 调用:

    await http.post("http://calikidsmap.com/test.php").then((response){

    var ddd=jsonDecode(response.body);

    Country_object_list = (ddd as List)
      .map((data) => new country.fromJson(data))
      .toList();

【讨论】:

    【解决方案3】:

    将此添加到pubspec.yaml

    dependencies:
      # Your other regular dependencies here
      json_annotation: <latest_version>
    
    dev_dependencies:
      # Your other dev_dependencies here
      build_runner: <latest_version>
      json_serializable: <latest_version>
    
    

    对象类。

    import 'package:json_annotation/json_annotation.dart';
    
    
    part 'user.g.dart'; //"user" is your dart file name
    
    /// JSON serialization logic to be generated.
    @JsonSerializable()
    
    class User {
      User(this.name, this.email);
    
      String name;
      String email;
    
      factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
    
      Map<String, dynamic> toJson() => _$UserToJson(this);
    }
    

    并在 Android Studio 的终端中运行。

    flutter pub run build_runner build
    

    现在像这样转换:

    Map results =  json.decode(response.body);
    User user = User.fromJson(results);
    

    来源https://flutter.dev/docs/development/data-and-backend/json

    【讨论】:

    • 工作得非常好。谢谢!
    【解决方案4】:

    同样的答案,但是,当您嵌套了 JsonObjects 时会发生什么? 简单:

    给定一个像这样的 jsonResponse:

    {
      "id": 1,
      "type": 15,
      "innerClass": {
        "id": 1,
        "type": "testing"
      }
    }
    

    这是代码外观的示例:

    class MainClass {
      int id = 0;
      int version = 0;
      InnerClass innerClass;
    
      MainClass (
          this.id,
          this.version,
          this.innerClass
          );
      
    //Create the same factory converter, but using another inner factory 'fromJson' converter
    //for the inner class object (InnerClass.fromJson(json['inner_class']))
    
      factory MainClass.fromJson(dynamic json) {
        return MainClass(
            json['id'] as int, // << put your json response keys instead.
            json['version'] as int,
            InnerClass.fromJson(json['innerClass']) // << this one
        );
      }
    

    然后,对内部类对象重复相同的策略:

    class InnerClass {
      int id = 0;
      String type = 'testing_type';
      InnerClass (
          this.id,
          this.type
          );
      factory InnerClass.fromJson(dynamic json) {
        return InnerClass(
            json['id'] as int,
            json['type'] as String
        );
      }
    }
    

    最后,你可以假设,在你项目的另一部分,像这样:

    try {
              mainClassDartObject = MainClass.fromJson(response.body);
         } catch (e) {
              print(e);
         }
    

    【讨论】:

      【解决方案5】:

      如果您想在请求后访问您的信息而无需额外步骤,这里是一个基本答案

       Map<String, dynamic> data = jsonDecode(response.body);
       String token = tokenData["data"]["access_token"];
      

      请求中的对象结构如下:

      {
        "success":1,
        "error":[],
        "data": {
           "access_token":"13d2ec9d1094903b1e81de8af059233e9f36ec4d",
           "expires_in":2628000,
           "token_type":"Bearer"
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-10-28
        • 2017-10-17
        • 2021-08-27
        • 1970-01-01
        • 1970-01-01
        • 2018-07-26
        • 1970-01-01
        • 2020-11-23
        • 2017-01-17
        相关资源
        最近更新 更多