简体   繁体   English

解析在 Dart 中具有嵌套对象数组的 JSON?

[英]Parsing JSON that has a nested array of objects in Dart?

I am making a Flutter app and I am using The MovieDB api to get data.我正在制作一个 Flutter 应用程序,我正在使用 MovieDB api 来获取数据。 When I call the api and ask for a specific movie, this is the general format that I get back:当我调用 api 并要求特定电影时,这是我返回的一般格式:

{
   "adult": false,
    "backdrop_path": "/wrqUiMXttHE4UBFMhLHlN601MZh.jpg",
    "belongs_to_collection": null,
    "budget": 120000000,
    "genres": [
        {
            "id": 28,
            "name": "Action"
        },
        {
            "id": 12,
            "name": "Adventure"
        },
        {
            "id": 878,
            "name": "Science Fiction"
        }
    ],
    "homepage": "http://www.rampagethemovie.com",
    "id": 427641,
    "imdb_id": "tt2231461",
    "original_language": "en",
    "original_title": "Rampage",
...
}

I have setup a model class for to parse this and the class is defined as such:我已经设置了一个模型类来解析它,并且该类定义如下:

import 'dart:async';

class MovieDetail {
  final String title;
  final double rating;
  final String posterArtUrl;
  final backgroundArtUrl;
  final List<Genre> genres;
  final String overview;
  final String tagline;
  final int id;

  const MovieDetail(
      {this.title, this.rating, this.posterArtUrl, this.backgroundArtUrl, this.genres, this.overview, this.tagline, this.id});

  MovieDetail.fromJson(Map jsonMap)
      : title = jsonMap['title'],
        rating = jsonMap['vote_average'].toDouble(),
        posterArtUrl = "http://image.tmdb.org/t/p/w342" + jsonMap['backdrop_path'],
        backgroundArtUrl = "http://image.tmdb.org/t/p/w500" + jsonMap['poster_path'],
        genres = (jsonMap['genres']).map((i) => Genre.fromJson(i)).toList(),
        overview = jsonMap['overview'],
        tagline = jsonMap['tagline'],
        id = jsonMap['id'];
}
class Genre {
  final int id;
  final String genre;

  const Genre(this.id, this.genre);

  Genre.fromJson(Map jsonMap)
    : id = jsonMap['id'],
      genre = jsonMap['name'];
}

My issue is that I can't get the genre to parse properly from the JSON.我的问题是我无法从 JSON 中正确解析流派。 When I get the JSON and pass it through my model class, I get the following error:当我获取 JSON 并通过我的模型类传递它时,我收到以下错误:

I/flutter (10874): type 'List<dynamic>' is not a subtype of type 'List<Genre>' where
I/flutter (10874):   List is from dart:core
I/flutter (10874):   List is from dart:core
I/flutter (10874):   Genre is from package:flutter_app_first/models/movieDetail.dart

I thought this would work because I have made a different class for the Genre object and passed in the JSON array as a list.我认为这会起作用,因为我为Genre对象创建了一个不同的类,并将 JSON 数组作为列表传入。 I don't understand how List<dynamic> isn't a child of List<Genre> because doesn't the keyword dynamic imply any object?我不明白List<dynamic>怎么不是List<Genre>的孩子,因为关键字dynamic暗示任何对象吗? Does anyone know how to parse a nested JSON array into custom objects?有谁知道如何将嵌套的 JSON 数组解析为自定义对象?

Try genres = (jsonMap['genres'] as List).map((i) => Genre.fromJson(i)).toList()尝试genres = (jsonMap['genres'] as List).map((i) => Genre.fromJson(i)).toList()

The issue: calling map without the cast makes it a dynamic call, which means the return type from Genre.fromJson is also dynamic (not Genre).问题:在没有Genre.fromJson情况下调用map使其成为动态调用,这意味着来自Genre.fromJson的返回类型也是动态的(不是 Genre)。

Take a look at https://flutter.io/json/ for some hints.查看https://flutter.io/json/以获得一些提示。

There are solutions, like https://pub.dartlang.org/packages/json_serializable , that makes this much easier有一些解决方案,比如https://pub.dartlang.org/packages/json_serializable ,可以让这变得更容易

我认为JSONtoDart 转换器非常有用,必须尝试...

Here is an example that is simple and easy to understand.这是一个简单易懂的例子。

With the JSON string as a nested object like this.将 JSON 字符串作为这样的嵌套对象。

{
  "title": "Dart Tutorial",
  "description": "Way to parse Json",
  "author": {
    "name": "bezkoder",
    "age": 30
  

} } There are 2 classes we can think about:我们可以考虑 2 个类:

  • User for author author User
  • Tutorial for {title, description, author} {title, description, author}教程

So we can define a new Tutorial like this.所以我们可以像这样定义一个新的教程。

class User {
  String name;
  int age;
  ...
}

class Tutorial {
  String title;
  String description;
  User author;

  Tutorial(this.title, this.description, this.author);

  factory Tutorial.fromJson(dynamic json) {
    return Tutorial(json['title'] as String, json['description'] as String, User.fromJson(json['author']));
  }

  @override
  String toString() {
    return '{ ${this.title}, ${this.description}, ${this.author} }';
  }
}

The main() function now looks like the following code. main() 函数现在看起来像下面的代码。 import 'dart:convert';导入“飞镖:转换”;

main() {
  String nestedObjText =
      '{"title": "Dart Tutorial", "description": "Way to parse Json", "author": {"name": "bezkoder", "age": 30}}';

  Tutorial tutorial = Tutorial.fromJson(jsonDecode(nestedObjText));

  print(tutorial);

Check the result, you can see our nested object:查看结果,可以看到我们嵌套的对象:

{ Dart Tutorial, Way to parse Json, { bezkoder, 30 } }

See that : Dart/Flutter parse JSON string into Nested Object请参阅: Dart/Flutter 将 JSON 字符串解析为嵌套对象

After receiving the response, first of all, you need to extract the arrays separately.收到响应后,首先需要分别提取数组。 Then you can easily map.然后就可以轻松映射了。 This is the way I do it.这就是我这样做的方式。

List<Attempts> attempts;
attempts=(jsonDecode(res.body)['message1'] as List).map((i) => Attempts.fromJson(i)).toList();
List<Posts> posts;
attempts=(jsonDecode(res.body)['message2'] as List).map((i) => Post.fromJson(i)).toList();

Refer below example.参考下面的例子。

   Future<List<Attempts>> getStatisticData() async {
    String uri = global.serverDNS + "PaperAttemptsManager.php";
    var res = await http.post(
      uri,
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: jsonEncode(<String, String>{
        'userName': widget.userId,
        'subject': widget.subjectName,
        'method': "GETPTEN",
      }),
    );

    if (res.statusCode == 200) {
      List<Attempts> attempts;
      attempts=(jsonDecode(res.body)['message'] as List).map((i) => Attempts.fromJson(i)).toList();
      return attempts;
    } else {
      throw "Can't get subjects.";
    }
  }

Model Class模型类

class Attempts {
  String message, userName, date, year, time;
  int status, id, marks, correctAnswers, wrongAnswers, emptyAnswers;

  Attempts({
    this.status,
    this.message,
    this.id,
    this.userName,
    this.date,
    this.year,
    this.marks,
    this.time,
    this.correctAnswers,
    this.wrongAnswers,
    this.emptyAnswers,
  });

  factory Attempts.fromJson(Map<String, dynamic> json) {
    return Attempts(
      status: json['status'],
      message: json['message'],
      id: json['ID'],
      userName: json['USERNAME'],
      date: json['DATE'],
      year: json['YEAR'],
      marks: json['MARKS'],
      time: json['TIME'],
      correctAnswers: json['CORRECT_ANSWERS'],
      wrongAnswers: json['WRONG_ANSWERS'],
      emptyAnswers: json['EMPTY_ANSWERS'],
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM