如何将嵌套的JSON转换为对象

时间:2019-04-10 14:20:53

标签: json dart flutter

我需要将Object作为正文参数发送到Post请求。我的对象是通过嵌套的Json创建的,到目前为止我无法正常工作。

我已经在JavaScript中非常轻松地完成了此操作,但是在Dart / Flutter中却没有找到实现此目的的方法。

我之前做过的“常规”方式很简单:

var data = {
      "email": "qwe@qwe.com",
      "password": "123",
      "first_name": "qweqwe",
      "billing": {
        "email": "qwe@qwe.com",
        "phone": "321654978",
      },
      "shipping": {
        "first_name": "qweqwe",
      }
    }

通过在Dart / Flutter中使用相同的结构,我得到了以下错误

  

[ERROR:flutter / lib / ui / ui_dart_state.cc(148)]未处理的异常:类型'_InternalLinkedHashMap'在强制类型转换中不是'String'类型的子类型

我尝试使用Map<String, dynamic>Map<String, String>,并使用模型作为数据模型。...

如果我发送相同的Json但没有"billing""shipping"(无嵌套Json),则它起作用。

3 个答案:

答案 0 :(得分:1)

在JSON中,值之间只能有逗号。

var data = {
  "email": "qwe@qwe.com",
  "password": "123",
  "first_name": "qweqwe",
  "billing": {
    "email": "qwe@qwe.com",
    "phone": "321654978"
  },
  "shipping": {
    "first_name": "qweqwe"
  }
}

在这里,我删除了“电话”和“名字”字段末尾的逗号。

答案 1 :(得分:1)

如果要上传data对象,则排序答案是将其转换为如下所示的字符串:

var jsonString = json.encode(data);
// upload jsonString as body to your server.
print("Json String is " + jsonString);

Map headers = {
  'Content-type' : 'application/json',
};

http.post("www.server.com/myPostEndpoint", body: jsonString, headers: headers);

就像评论中讨论的那样,您可能需要将整个内容包装在data属性中。您可以尝试以下方法:

var payload = {   
    "data": {
       "email": "qwe@qwe.com",
       "password": "123",
       "first_name": "qweqwe",
       "billing": {
         "email": "qwe@qwe.com",
         "phone": "321654978",
       },
       "shipping": {
         "first_name": "qweqwe",
       }   
   } 
};

var jsonString = json.encode(payload); // upload jsonString as body to your server. print("Json String is " + jsonString);

Map headers = {   'Content-type': 'application/json', };

http.post("www.server.com/myPostEndpoint", body: jsonString, headers: headers);

tl; dr

创建模型总是一个好主意。 因此,这可能是您的User模型:

class User {
  final String email;
  final String password;
  final String firstName;
  final Map<String, String> billing;
  final Map<String, String> shipping;

  User({this.email, this.password, this.firstName, this.billing, this.shipping});

  static User fromJson(dynamic json) {
    return User(
      email: json["email"],
      password: json["password"],
      firstName: json["first_name"],
      billing: json["billing"],
      shipping: json["shipping"],
    );
  }

}

它有一个静态构造函数,可以像从您一样从解码的json片段创建此User的实例。

现在您可以继续在代码中使用此模型,如下所示:

var data = {
  "email": "qwe@qwe.com",
  "password": "123",
  "first_name": "qweqwe",
  "billing": {
    "email": "qwe@qwe.com",
    "phone": "321654978",
  },
  "shipping": {
    "first_name": "qweqwe",
  }
};


var user = User.fromJson(data);

print("Users Email is ${user.billing["email"]}");

同时为BillingShipping创建模型甚至更干净。

这是一个完整的示例,其中还包括toJson()方法,用于从已解析的模型生成Json:

class User {
  final String email;
  final String password;
  final String firstName;
  final Billing billing;
  final Shipping shipping;

  User({this.email, this.password, this.firstName, this.billing, this.shipping});

  static User fromJson(dynamic json) {
    return User(
      email: json["email"],
      password: json["password"],
      firstName: json["first_name"],
      billing: Billing.fromJson(json["billing"]),
      shipping: Shipping.fromJson(json["shipping"]),
    );
  }

  Map<String, dynamic> toJson() => {'email': email, 'password': password, 'first_name': firstName, 'billing': billing.toJson(), 'shipping': shipping.toJson()};
}

class Billing {
  final String email;
  final String phone;

  Billing({this.email, this.phone});

  static Billing fromJson(dynamic json) {
    return Billing(email: json["email"], phone: json["phone"]);
  }

  Map<String, dynamic> toJson() => {'email': email, 'phone': phone};
}

class Shipping {
  final String name;

  Shipping({
    this.name,
  });

  static Shipping fromJson(dynamic json) {
    return Shipping(
      name: json["first_name"],
    );
  }


  Map<String, dynamic> toJson() => {'name': name};
}

这是您可以使用的方式:

var data = {
  "email": "qwe@qwe.com",
  "password": "123",
  "first_name": "qweqwe",
  "billing": {
    "email": "qwe@qwe.com",
    "phone": "321654978",
  },
  "shipping": {
    "first_name": "qweqwe",
  }
};


var user = User.fromJson(data);

print("Users Email is ${user.billing.email}");
print("Shipping name is ${user.shipping.name}");

var jsonString = json.encode(user.toJson()); // upload this as body to your server.
print("Json String is " + jsonString);

答案 2 :(得分:0)

我认为其他答案可能(非常)使这一问题变得过于复杂。无论使用哪种语言,将JSON发送到服务器,都需要将数据以 string 的形式发送,并使用[7] pry(#<#<Class:0x007fecc2fdafc8>>)> Service.where(:client_id => client_ids).each{|s| services[s.id] = {:name => s.name, :frequency_name => s.frequency_short_text, :per_hour => s.per_hour?} } ArgumentError: wrong number of arguments (2 for 1) from /Users/justin/.rvm/gems/ruby-2.1.10/gems/postgres_ext-2.0.0/lib/postgres_ext/arel/visitors/to_sql.rb:6:in `visit_Array' 内容类型。 application/json已经可以处理嵌套的地图,因此您不需要做任何特殊的事情...根本:

json.encode

这就是您需要做的。确实不需要使用// Replace the "..." with the rest of your data. var data = {"email": "qwe@qwe.com", "password": "123", ...} // `asJson` is a String. var asJson = json.encode(data); // Send it var response = await client.post('example.com/...', body: asJson, headers: {'content-type', 'application/json'}); User等来制作整个fromJson类。

至于该错误-toJson,我不知道 exact 是什么原因,因为您没有提供相关代码,但是很明显,在某些时候,您给出了在期望有String的地方将Map扔到地图上。就像您说的那样,您已经尝试过Unhandled Exception: type '_InternalLinkedHashMap' is not a subtype of type 'String' in type castMap<String, dynamic>,但是真正需要的是Map<String, String

如果您尚未使用Dart分析器(通常在IDE插件中),则很容易发现这种错误。

希望这对您有帮助!

TLDR:调用String以获得json.encode(data),然后将该String以及String内容类型发送到服务器。