如何在Flutter中将Response JSON转换为Object?

时间:2018-10-26 05:12:55

标签: json http dart flutter

我正在尝试将成功的JSON字符串转换为Object。可能是我的工作方式不正确,但是我有几个与将JSON转换为对象有关的问题。

我也在Log中得到了这个证据。

NoSuchMethodError:类' _InternalLinkedHashMap'没有实例方法'cast'具有匹配的参数
接收者:_LinkedHashMap len:3 尝试致电:cast>()

Q1。我是否还需要在模型中强制转换该数据对象?
Q2。这是将JSON转换为Object(SignUpResponse)的最佳和简单方法。
Q3。与序列化比较好吗?

响应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转换为垂直对象?

5 个答案:

答案 0 :(得分:3)

不需要使用强制转换,您可以直接解析为地图

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

答案 1 :(得分:1)

JSON:

clc
clear all
close all
img=imread('star.jpg');
binary_image=convert2binary(img);
imshow(binary_image);
visited = false(size(binary_image));
[rows, cols] = size(binary_image);
B = zeros(rows, cols);
ID_counter = 1;
for row = 1:rows
    for col = 1:cols
        if binary_image(row, col) == 0
            visited(row, col) = true;
        elseif visited(row, col)
            continue;
        else
            stack = [row col];

            while ~isempty(stack)
                loc = stack(1,:);
                stack(1,:) = [];

                if visited(loc(1),loc(2))
                    continue;
                end

                visited(loc(1),loc(2)) = true;
                B(loc(1),loc(2)) = ID_counter;

                [locs_y, locs_x] = meshgrid(loc(2)-1:loc(2)+1, loc(1)-1:loc(1)+1);
                locs_y = locs_y(:);
                locs_x = locs_x(:);

                out_of_bounds = locs_x < 1 | locs_x > rows | locs_y < 1 | locs_y > cols;
                locs_y(out_of_bounds) = [];
                locs_x(out_of_bounds) = [];
                is_visited = visited(sub2ind([rows cols], locs_x, locs_y));

                locs_y(is_visited) = [];
                locs_x(is_visited) = [];

                is_1 = binary_image(sub2ind([rows cols], locs_x, locs_y));
                locs_y(~is_1) = [];
                locs_x(~is_1) = [];

                stack = [stack; [locs_x locs_y]];
            end

            ID_counter = ID_counter + 1;
        end
    end
end

function [binary] = convert2binary(img)

    [x, y, z]=size(img);
    if z==3
        img=rgb2gray(img);
    end

    img=double(img);
    sum=0;
    for i=1:x
        for j=1:y
            sum=sum+img(i, j);
        end
    end


    threshold=100  % or sum/(x*y);
    binary=zeros(x,y);

    for i=1:x
        for j=1:y
            if img(i, j) >= threshold
                binary(i, j) = 1;
            else
                binary(i, j)=0;
            end
        end
    end
end

POJO类:

    [
     {
       "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"
       },
    ]

API调用:

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

答案 2 :(得分:1)

相同的答案,但是,当您嵌套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);
     }

答案 3 :(得分:0)

  
    

Q2。这是将JSON转换为Object(SignUpResponse)的最佳和简单方法。

  

使用在线工具(如您在问题中所写)创建的生成数据模型,或使用可离线使用的类似工具。

这是在脱机模式下(本地安装在计算机上)由同一工具生成的代码的示例。

// Generated by 'yaml2podo'
// Version: 0.1.11
// https://pub.dev/packages/yaml2podo

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

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

  factory Data.fromJson(Map map) {
    return Data(
        zipCode: map['zipCode'] as String,
        area: map['area'] as String,
        id_: map['_id'] as String,
        isPauseDelivery: map['isPauseDelivery'] as bool,
        email: map['email'] as String,
        vacationEndDt: map['vacationEndDt'],
        phoneNumber: map['phoneNumber'] as String,
        isAddressApproved: map['isAddressApproved'] as int,
        streetAddress: map['streetAddress'] as String,
        todayOrder: map['todayOrder'] as int,
        defaultLiter: map['defaultLiter'] as int,
        totalOrder: map['totalOrder'] as int,
        vacationStartDt: map['vacationStartDt'],
        unitNumber: map['unitNumber'] as String);
  }

  Map<String, dynamic> toJson() {
    var result = <String, dynamic>{};
    result['zipCode'] = zipCode;
    result['area'] = area;
    result['_id'] = id_;
    result['isPauseDelivery'] = isPauseDelivery;
    result['email'] = email;
    result['vacationEndDt'] = vacationEndDt;
    result['phoneNumber'] = phoneNumber;
    result['isAddressApproved'] = isAddressApproved;
    result['streetAddress'] = streetAddress;
    result['todayOrder'] = todayOrder;
    result['defaultLiter'] = defaultLiter;
    result['totalOrder'] = totalOrder;
    result['vacationStartDt'] = vacationStartDt;
    result['unitNumber'] = unitNumber;
    return result;
  }
}

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

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

  factory SignUpResponse.fromJson(Map map) {
    return SignUpResponse(
        error: map['error'] as bool,
        data: _toObject(map['data'], (e) => Data.fromJson(e as Map)),
        message: map['message'] as String);
  }

  Map<String, dynamic> toJson() {
    var result = <String, dynamic>{};
    result['error'] = error;
    result['data'] = data?.toJson();
    result['message'] = message;
    return result;
  }
}

T _toObject<T>(dynamic data, T Function(dynamic) fromJson) {
  if (data == null) {
    return null;
  }
  return fromJson(data);
}

/*
SignUpResponse:
  "data": Data
  "message": String
  "error": bool

Data:
  "_id": String
  "email": String
  "phoneNumber": String
  "isAddressApproved": int
  "unitNumber": String
  "streetAddress": String
  "area": String
  "zipCode": String
  "totalOrder": int
  "todayOrder": int
  "isPauseDelivery": bool
  "vacationStartDt": Object
  "vacationEndDt": Object
  "defaultLiter": int
*/

答案 4 :(得分:0)

将此添加到 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