【问题标题】:How to Deserialize a list of objects from json in flutter如何在颤动中反序列化来自json的对象列表
【发布时间】:2018-12-05 19:52:53
【问题描述】:

我正在使用 dart 包 json_serializable 进行 json 序列化。查看颤振文档,它显示了如何反序列化单个对象,如下所示:

Future<Post> fetchPost() async {
  final response =
  await http.get('https://jsonplaceholder.typicode.com/posts/1');

  if (response.statusCode == 200) {
  // If the call to the server was successful, parse the JSON
  return Post.fromJson(json.decode(response.body));
  } else {
    // If that call was not successful, throw an error.
    throw Exception('Failed to load post');
  }
}

但是,我对 dart 不够熟悉,无法弄清楚如何对项目列表而不是单个实例执行相同操作。

【问题讨论】:

  • 好吧,它解码响应正文,并将其传递给本质上的 POST 构造函数。如果你解码的 JSON 是一个数组,你需要循环它并构建一个 Posts 数组。这就是你要问的吗?检查解码的类型以确保它是可迭代的,然后执行类似于:List&lt;Post&gt; posts = json.decode(response.body).map((Map m)=&gt; Json.fromJson(m)).toList();

标签: json dart flutter


【解决方案1】:

好吧,您的服务将处理作为地图的响应正文或相应的地图列表。根据您拥有的代码,您计入 1 项。

如果响应正文是可迭代的,那么如果我正确理解您的问题,您需要进行相应的解析和遍历。

例子:

Iterable l = json.decode(response.body);
List<Post> posts = List<Post>.from(l.map((model)=> Post.fromJson(model)));

帖子是帖子列表。

编辑:我想在这里添加一个清晰的说明。这里的目的是解码返回的响应。下一步是将 JSON 对象的可迭代对象转换为对象的实例。这是通过在您的类中创建 fromJson 方法来正确获取 JSON 并相应地实现它来完成的。下面是一个示例实现。

class Post {
  // Other functions and properties relevant to the class
  // ......
  /// Json is a Map<dynamic,dynamic> if i recall correctly.
  static fromJson(json): Post {
    Post p = new Post()
    p.name = ...
    return p
  }
}

这些天我有点从 Dart 中抽象出来,支持更好的实用程序来完成需要完成的任务。所以我的语法可能有点偏差,但这是伪代码。

【讨论】:

  • 我在尝试这个时似乎遇到了一些内部转换错误。 _TypeError (type '(Map&lt;dynamic, dynamic&gt;) =&gt; UserInfoV1' is not a subtype of type '(dynamic) =&gt; dynamic' of 'f')
  • 这是一个绝妙的解决方案,可以与 jsonserializer lib 混合使用,但是在 map 函数中存在错误(可能是 dart 版本更改了 api) List posts = l.map((model )=> Post.fromJson(model)).toList();
  • 正确的解决方法是:List&lt; Item &gt; itemsList= List&lt; Item &gt;.from(parsedListJson.map((i) =&gt; Item.fromJson(i)));以上代码语法无效,无法编译
  • 谢谢@Quinn。也许 Dart 多年来略有变化,所以我认为有些事情会发生变化。我猜 toList 不再是正确的语法,Array.from() 是当今最好的解决方案?
  • @OjonugwaJudeOchalifu 这是一篇旧帖子,在撰写本文时是正确的。我会更新答案。
【解决方案2】:

我一直用这种方式没问题;

List<MyModel> myModels;
var response = await http.get("myUrl");

myModels=(json.decode(response.body) as List).map((i) =>
              MyModel.fromJson(i)).toList();

【讨论】:

  • 直截了当,解决了问题。您也可以使用下面的 URL 将您的 JSON 字符串映射到 dart 类。 javiercbk.github.io/json_to_dart
  • 这个 URL 总能节省我的时间,但需要注意变量带有空值。如果嵌套对象列表需要,我更喜欢将代码块更改为我的样式。
  • 其实我很困惑fromJson,它来自哪里?
  • 来自 json 的@Bayu 是您的模型中定义的工厂函数。如果您使用 app.quicktype.iojaviercbk.github.io/json_to_dart 网站从您的 json 创建模型,它们将为您创建一切。
  • @UchennaNnodim 你是山羊
【解决方案3】:

你也可以这样做

  List<dynamic> parsedListJson = jsonDecode("your json string");
  List<Item> itemsList = List<Item>.from(parsedListJson.map((i) => Item.fromJson(i)));

其中Item 是您的自定义类,您在其中实现了toJsonfromJson

【讨论】:

  • 这是唯一对我有用的解决方案 ^^^^^^^^^^^^^^^^^^^^ 其他一切都给出了与无法转换相关的编译错误dynamic 到我试图解组的对象类型
  • parsedListJson 在哪里?它是来自 Dart 还是 3rd 方包?我收到一个错误,Undefined name 'parsedListJson'.
  • 我现在明白了。这是您要解析的列表(即它不是框架的元素)。
  • 这对我有用。我有List&lt;PlayingCard&gt; cards,它可以很容易地编码成一个 JSON 扑克牌数组。解码很麻烦,但这个方法奏效了!
  • 帮助苦苦挣扎的新人飞镖。我使用 http.get 调用中的 response.body 而不是“你的 json 字符串”,例如:List&lt;dynamic&gt; parsedListJson = jsonDecode(response.body);
【解决方案4】:

只是另一个关于 JSON 解析的示例,以供进一步说明。

假设我们要解析 JSON 对象中的 items 数组。

factory YoutubeResponse.fromJSON(Map<String, dynamic> YoutubeResponseJson) 
 {

// Below 2 line code is parsing JSON Array of items in our JSON Object (YouttubeResponse)


var list = YoutubeResponseJson['items'] as List;
List<Item> itemsList = list.map((i) => Item.fromJSON(i)).toList();

return new YoutubeResponse(
    kind: YoutubeResponseJson['kind'],
    etag: YoutubeResponseJson['etag'],
    nextPageToken: YoutubeResponseJson['nextPageToken'],
    regionCode: YoutubeResponseJson['regionCode'],
    mPageInfo: pageInfo.fromJSON(YoutubeResponseJson['pageInfo']),

    // Here we are returning parsed JSON Array.

    items: itemsList);

  }

【讨论】:

  • 未处理的异常:类型'List'不是类型'List'的子类型
  • 能否请您发布一些您的 json 响应。
【解决方案5】:

首先,创建一个与您的 json 数据匹配的类,在我的例子中,我创建(生成)名为 Img 的类:

import 'dart:convert';

Img imgFromJson(String str) => Img.fromJson(json.decode(str));
String imgToJson(Img data) => json.encode(data.toJson());

class Img {
    String id;
    String img;
    dynamic decreption;

    Img({
        this.id,
        this.img,
        this.decreption,
    });

    factory Img.fromJson(Map<String, dynamic> json) => Img(
        id: json["id"],
        img: json["img"],
        decreption: json["decreption"],
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "img": img,
        "decreption": decreption,
    };
}

PS。您可以使用app.quicktype.io 在 dart 中生成您的 json 数据类。 然后将您的帖子/获取发送到您的服务器:

Future<List<Img>> _getimages() async {
    var response = await http.get("http://192.168.115.2/flutter/get_images.php");
    var rb = response.body;

    // store json data into list
    var list = json.decode(rb) as List;

    // iterate over the list and map each object in list to Img by calling Img.fromJson
    List<Img> imgs = list.map((i)=>Img.fromJson(i)).toList();

    print(imgs.runtimeType); //returns List<Img>
    print(imgs[0].runtimeType); //returns Img

    return imgs;
}

更多信息请见Parsing complex JSON in Flutter

【讨论】:

    【解决方案6】:

    按照以下步骤操作:

    1. 创建一个模型类(命名为 LoginResponse):click here to convert json to dart

    2. LoginResponce loginResponce=LoginResponce.fromJson(json.decode(response.body));

    3. 现在您可以在模型实例中获取数据(如 loginResponce )。

    【讨论】:

    • 这是一个了不起的方法。它不是设置 dart 代码生成或花费数小时来弄清楚反序列化的细节,而是一个用于测试试点和试验的在线反序列化器。很好的答案,谢谢
    【解决方案7】:

    例如,数组中的每一项都是一个 JSON 对象。

    {
      "tags": [
        {
          "name": "dart",
          "quantity": 12
        },
        {
          "name": "flutter",
          "quantity": 25
        },
        {
          "name": "json",
          "quantity": 8
        }
      ]
    }
    

    我们需要一个代表标签项的类。所以我们创建了 Tag 类,其中包含 2 个这样的字段。

    class Tag {
      String name;
      int quantity;
    
      Tag(this.name, this.quantity);
    
      factory Tag.fromJson(dynamic json) {
        return Tag(json['name'] as String, json['quantity'] as int);
      }
    
      @override
      String toString() {
        return '{ ${this.name}, ${this.quantity} }';
      }
    }
    

    factory Tag.fromJson(dynamic json) 方法会将dynamic 对象解析为Tag 对象。我们将在映射步骤的main() 函数中需要它。

    import 'dart:convert';
    
    main() {
      String arrayObjsText =
          '{"tags": [{"name": "dart", "quantity": 12}, {"name": "flutter", "quantity": 25}, {"name": "json", "quantity": 8}]}';
    
      var tagObjsJson = jsonDecode(arrayObjsText)['tags'] as List;
      List<Tag> tagObjs = tagObjsJson.map((tagJson) => Tag.fromJson(tagJson)).toList();
    
      print(tagObjs);
    }
    

    让我解释一下上面的代码。这很简单。 – jsonDecode()'tags' JSON 对象转换为 dynamic 对象。然后我们使用方括号['tags'] 来获取其中的 JSON 数组。 – 因为List 返回一个List&lt;dynamic&gt;,我们将使用map()List 的每个dynamic 项更改为Tag 对象。 – 最后,.toList() 将上面的 Iterable 结果转换为List&lt;Tag&gt; 对象。

    现在,如果我们运行代码,结果将是这样的。

    [{ dart, 12 }, { flutter, 25 }, { json, 8 }]
    

    【讨论】:

      【解决方案8】:

      这是我的模型类 -

        class SuggestedMovie {
        String title;
        String genres;
        int movieId;
        SuggestedMovie({this.title, this.genres, this.movieId});
        factory SuggestedMovie.fromJson(Map<dynamic, dynamic> parsedJson) {
          return SuggestedMovie(
            movieId: parsedJson['movieId'],
            title: parsedJson['title'] as String,
            genres: parsedJson['genres'] as String,
          );
        }
      }
      

      下面是把 JSON 响应反序列化成 List 的代码

       suggestedMovie = (json.decode(jsonResponse.data) as List)
            .map((i) => SuggestedMovie.fromJson(i))
            .toList();
      

      【讨论】:

        【解决方案9】:

        如何在flutter中反序列化json中的对象列表

        import 'package:json_helpers/json_helpers.dart';
        
        void main() {
          // String request.body
          final body = '[{"name": "Jack"}, {"name": "John"} ]';
          final personList = body.jsonList((e) => Person.fromJson(e));
          assert(personList[1].name == 'John');
          print(personList[1].name);
        }
        
        class Person {
          final String name;
        
          Person({required this.name});
        
          factory Person.fromJson(Map<String, dynamic> json) {
            return Person(
              name: json['name'] as String,
            );
          }
        }
        
        

        【讨论】:

          【解决方案10】:

          启用强模式后,由于缺少类型信息,上述解决方案都不会真正编译。

          从 dart 2.14 开始编译,启用强模式:

          analysis_options.yaml

          
          include: package:lints/recommended.yaml
          
          analyzer:
            strong-mode:
              implicit-casts: false
              implicit-dynamic: false
          
          
              import 'dart:convert';
          
              // read the json file. This example use dcli but you just
              // need [source] to contain the json string.
              var source = dcli.read(_failedTrackerFilename).toParagraph();
          
              var l = json.decode(source) as Iterable;
              var failures = List<UnitTest>.from(l.map<UnitTest>(
                    (dynamic i) => UnitTest.fromJson(i as Map<String, dynamic>)));
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-04-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多