【问题标题】:How to convert a nested JSON into an Object如何将嵌套的 JSON 转换为对象
【发布时间】:2019-09-01 01:13:54
【问题描述】:

我需要将 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),它可以工作。

【问题讨论】:

标签: json dart flutter


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    如果您想上传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);
    

    就像在 cmets 中讨论的那样,您可能需要将整个内容包装在 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"]}");
    

    同时为Billing 和Shipping 创建模型会更简洁。

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

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

    【讨论】:

    • 当我使用模型作为参数时,我得到Invalid request body "Instance of 'User'" 我需要的是能够将对象作为主体参数发送,而不仅仅是解析它......我被困了几个这几天......我现在没有想法
    • 作为参数怎么用?
    • 在我的问题中说我需要这个来发送“转换后的”Json 作为 Http Post 请求的参数
    • 哦,是的,我很抱歉。一定误解了你的问题。请看看我的编辑。它现在已经为您的帖子正文生成了一个 json 字符串。
    • 看看我回答的最上面。也许这就是您要搜索的内容。
    【解决方案3】:

    我认为其他答案可能(非常)过度复杂化。无论您使用哪种语言,要将 JSON 发送到服务器,您都需要将数据作为 string 发送,内容类型为 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'});
    

    这就是你需要做的。真的不需要用fromJson、toJson 等创建一个完整的User 类。

    至于这个错误 - Unhandled Exception: type '_InternalLinkedHashMap' is not a subtype of type 'String' in type cast,我不知道是什么确切原因,因为你没有提供相关代码,但很明显,在某些时候,你给了 Dart映射它期望字符串的位置。正如您所说,您已经尝试过Map&lt;String, dynamic&gt; 和Map&lt;String, String,但真正需要的是String。

    如果您还没有使用 Dart 分析器(通常在 IDE 插件中),这是可以轻松捕获的错误类型。

    希望这有帮助!

    TLDR:调用json.encode(data)获取String,然后将String连同application/json内容类型一起发送到服务器。

    【讨论】:

    • “失败”是什么意思?您是否收到运行时错误,或者服务器本身是否向您发送错误?如果你不说...
    猜你喜欢
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    相关资源
    最近更新 更多