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

25

我正在开发一个Flutter应用,使用The MovieDB API获取数据。当我调用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",
...
}

我已经设置了一个模型类来解析它,该类定义如下:

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'];
}

我的问题是我无法正确从JSON中解析出流派。当我获取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

我认为这应该行得通,因为我为Genre对象创建了一个不同的类,并将JSON数组作为列表传递进去。我不明白为什么List<dynamic>不是List<Genre>的子项,因为关键字dynamic不是意味着任何对象吗?有人知道如何将嵌套的JSON数组解析为自定义对象吗?
3个回答

48

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

问题在于没有强制类型转换,这会使得map成为一个动态调用,这意味着Genre.fromJson的返回类型也是动态的(而不是Genre类型)。

查看https://flutter.io/json/ 获取一些提示。

有解决方案,例如https://pub.dartlang.org/packages/json_serializable ,这会让事情变得更加简单。


1
在类型转换中,'String' 类型不是 'List<dynamic>' 类型的子类型。这是由于 Dart 无法正确地将 jsonMap['genres'] 的内部列表从字符串转换为列表。实际上,jsonMap['genres'] 仍然是一个字符串,因为 jsonDecode 失败了。 - Alessandro Ornano
1
@AlessandroOrnano 首先使用 jsonDecode(jsonMap['genres']) - GeekLei

24

1
收到响应后,首先需要单独提取数组。然后你可以很容易地进行映射。这是我做的方式。
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();

请看下面的示例。
   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.";
    }
  }

模型类
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'],
    );
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接