List<dynamic> 类型不是 Map<String dynamic> 类型的子类型

Posted

技术标签:

【中文标题】List<dynamic> 类型不是 Map<String dynamic> 类型的子类型【英文标题】:Type List<dynamic> is not a subtype of type Map<String dynamic> 【发布时间】:2021-10-25 19:52:57 【问题描述】:

我是 Flutter 编程的新手,我正在尝试导入一个本地 JSON 文件,其中包含书籍数据,如书名、作者、发行年份等。

最初我使用 JSON 到 DART 转换器来组装书籍数据模型,现在我正在尝试创建一个 getBooksAll() 函数,程序在该函数中获取本地 JSON 文件并使用来自 @ 的 fromJson() 方法987654323@ 类将数据解析为 Map。

我遇到的问题是json.decode(value) 返回一个类型List&lt;dynamic&gt;,而fromJson() 方法接受一个类型Map&lt;String, dynamic&gt;我将如何解决这个问题?

这里是getBooksAll() 代码:

  static getBooksAll() 
    var booksJson = rootBundle.loadString('assets/bookData.json');
    booksJson.then((value) => BookData.fromJson(json.decode(value)));
  

这是我得到的错误:

E/flutter (10608): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
E/flutter (10608): #0      BookData.getBooksAll.<anonymous closure> (package:well_red_v1/models/book_data_model.dart:56:54)
E/flutter (10608): #1      _rootRunUnary (dart:async/zone.dart:1436:47)
E/flutter (10608): #2      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
E/flutter (10608): <asynchronous suspension>
E/flutter (10608): 

这里是整本书的数据模型代码:

import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:flutter/services.dart' show rootBundle;

class BookData 
  Id? id;
  String? title;
  String? isbn;
  int? pageCount;
  PublishedDate? publishedDate;
  String? thumbnailUrl;
  String? shortDescription;
  String? longDescription;
  String? status;
  List<dynamic>? authors;
  List<dynamic>? categories;

  BookData(this.id, this.title, this.isbn, this.pageCount, this.publishedDate, this.thumbnailUrl, this.shortDescription, this.longDescription, this.status, this.authors, this.categories);

  BookData.fromJson(Map<String, dynamic> json) 
    this.id = json["_id"] == null ? null : Id.fromJson(json["_id"]);
    this.title = json["title"];
    this.isbn = json["isbn"];
    this.pageCount = json["pageCount"];
    this.publishedDate = json["publishedDate"] == null ? null : PublishedDate.fromJson(json["publishedDate"]);
    this.thumbnailUrl = json["thumbnailUrl"];
    this.shortDescription = json["shortDescription"];
    this.longDescription = json["longDescription"];
    this.status = json["status"];
    this.authors = json["authors"] ?? [];
    this.categories = json["categories"] ?? [];
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if(this.id != null)
      data["_id"] = this.id?.toJson();
    data["title"] = this.title;
    data["isbn"] = this.isbn;
    data["pageCount"] = this.pageCount;
    if(this.publishedDate != null)
      data["publishedDate"] = this.publishedDate?.toJson();
    data["thumbnailUrl"] = this.thumbnailUrl;
    data["shortDescription"] = this.shortDescription;
    data["longDescription"] = this.longDescription;
    data["status"] = this.status;
    if(this.authors != null)
      data["authors"] = this.authors;
    if(this.categories != null)
      data["categories"] = this.categories;
    return data;
  

  static getBooksAll() 
    var booksJson = rootBundle.loadString('assets/bookData.json');
    booksJson.then((value) => BookData.fromJson(json.decode(value)));
  


class PublishedDate 
  String? $date;

  PublishedDate(this.$date);

  PublishedDate.fromJson(Map<String, dynamic> json) 
    this.$date = json["$$date"];
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["$$date"] = this.$date;
    return data;
  


class Id 
  String? $oid;

  Id(this.$oid);

  Id.fromJson(Map<String, dynamic> json) 
    this.$oid = json["$$oid"];
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["$$oid"] = this.$oid;
    return data;
  

这是 JSON 文件的一部分:

[
  
    "_id": 1,
    "title": "Unlocking android",
    "isbn": "1933988673",
    "pageCount": 416,
    "publishedDate": 
      "$date": "2009-04-01T00:00:00.000-0700"
    ,
    "thumbnailUrl": "https://s3.amazonaws.com/AKIAJC5RLADLUMVRPFDQ.book-thumb-images/ableson.jpg",
    "shortDescription": "Unlocking Android: A Developer's Guide provides concise, hands-on instruction for the Android operating system and development tools. This book teaches important architectural concepts in a straightforward writing style and builds on this with practical and useful examples throughout.",
    "longDescription": "Android is an open source mobile phone platform based on the Linux operating system and developed by the Open Handset Alliance, a consortium of over 30 hardware, software and telecom companies that focus on open standards for mobile devices. Led by search giant, Google, Android is designed to deliver a better and more open and cost effective mobile experience.    Unlocking Android: A Developer's Guide provides concise, hands-on instruction for the Android operating system and development tools. This book teaches important architectural concepts in a straightforward writing style and builds on this with practical and useful examples throughout. Based on his mobile development experience and his deep knowledge of the arcane Android technical documentation, the author conveys the know-how you need to develop practical applications that build upon or replace any of Androids features, however small.    Unlocking Android: A Developer's Guide prepares the reader to embrace the platform in easy-to-understand language and builds on this foundation with re-usable Java code examples. It is ideal for corporate and hobbyists alike who have an interest, or a mandate, to deliver software functionality for cell phones.    WHAT'S INSIDE:        * Android's place in the market      * Using the Eclipse environment for Android development      * The Intents - how and why they are used      * Application classes:            o Activity            o Service            o IntentReceiver       * User interface design      * Using the ContentProvider to manage data      * Persisting data with the SQLite database      * Networking examples      * Telephony applications      * Notification methods      * OpenGL, animation & multimedia      * Sample Applications  ",
    "status": "PUBLISH",
    "authors": [
      "W. Frank Ableson",
      "Charlie Collins",
      "Robi Sen"
    ],
    "categories": [
      "Open Source",
      "Mobile"
    ]
  ,
  
    "_id": 2,
    "title": "Android in Action, Second Edition",
    "isbn": "1935182722",
    "pageCount": 592,
    "publishedDate": 
      "$date": "2011-01-14T00:00:00.000-0800"
    ,
    "thumbnailUrl": "https://s3.amazonaws.com/AKIAJC5RLADLUMVRPFDQ.book-thumb-images/ableson2.jpg",
    "shortDescription": "Android in Action, Second Edition is a comprehensive tutorial for Android developers. Taking you far beyond \"Hello Android,\" this fast-paced book puts you in the driver's seat as you learn important architectural concepts and implementation strategies. You'll master the SDK, build WebKit apps using html 5, and even learn to extend or replace Android's built-in features by building useful and intriguing examples. ",
    "longDescription": "When it comes to mobile apps, Android can do almost anything   and with this book, so can you! Android runs on mobile devices ranging from smart phones to tablets to countless special-purpose gadgets. It's the broadest mobile platform available.    Android in Action, Second Edition is a comprehensive tutorial for Android developers. Taking you far beyond \"Hello Android,\" this fast-paced book puts you in the driver's seat as you learn important architectural concepts and implementation strategies. You'll master the SDK, build WebKit apps using HTML 5, and even learn to extend or replace Android's built-in features by building useful and intriguing examples. ",
    "status": "PUBLISH",
    "authors": [
      "W. Frank Ableson",
      "Robi Sen"
    ],
    "categories": [
      "Java"
    ]
  ,
  
    "_id": 3,
    "title": "Specification by Example",
    "isbn": "1617290084",
    "pageCount": 0,
    "publishedDate": 
      "$date": "2011-06-03T00:00:00.000-0700"
    ,
    "thumbnailUrl": "https://s3.amazonaws.com/AKIAJC5RLADLUMVRPFDQ.book-thumb-images/adzic.jpg",
    "status": "PUBLISH",
    "authors": [
      "Gojko Adzic"
    ],
    "categories": [
      "Software Engineering"
    ]
  
]

【问题讨论】:

你能添加你的JSON文件结构数据吗? 是的,当然。只加了一部分。实际文件很长。 【参考方案1】:

对象列表映射解决方案:

  static getBooksAll() async 
    var bookURL =
        "https://raw.githubusercontent.com/dineshnagarajandev/samplejson/main/books.json";
    var response = await http.get(Uri.parse(bookURL));
    var listToPass = jsonDecode(response.body);
    List<BookData> bookData =
        List<BookData>.from(listToPass.map((i) => BookData.fromJson(i)));
    print(bookData);
  

注意:Id 类存在类型问题,需要更新。您使用的 id 是 int,但声明为 String

查看解决方案评论

this.id = json["_id"] == null ? null : Id.fromJson(json["_id"]);

编辑:

您使用的模型没有_id 作为对象。您可以删除您的 ID 类并使用以下内容更新您的模型

class BookData 
  int? id;
  String? title;
  String? isbn;
  int? pageCount;
  PublishedDate? publishedDate;
  String? thumbnailUrl;
  String? shortDescription;
  String? longDescription;
  String? status;
  List<dynamic>? authors;
  List<dynamic>? categories;

  BookData(
      this.id,
      this.title,
      this.isbn,
      this.pageCount,
      this.publishedDate,
      this.thumbnailUrl,
      this.shortDescription,
      this.longDescription,
      this.status,
      this.authors,
      this.categories);

  BookData.fromJson(Map<String, dynamic> json) 
    this.id = json["_id"] == null ? null : json["_id"];
    this.title = json["title"];
    this.isbn = json["isbn"];
    this.pageCount = json["pageCount"];
    this.publishedDate = json["publishedDate"] == null
        ? null
        : PublishedDate.fromJson(json["publishedDate"]);
    this.thumbnailUrl = json["thumbnailUrl"];
    this.shortDescription = json["shortDescription"];
    this.longDescription = json["longDescription"];
    this.status = json["status"];
    this.authors = json["authors"] ?? [];
    this.categories = json["categories"] ?? [];
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.id != null) data["_id"] = this.id;
    data["title"] = this.title;
    data["isbn"] = this.isbn;
    data["pageCount"] = this.pageCount;
    if (this.publishedDate != null)
      data["publishedDate"] = this.publishedDate?.toJson();
    data["thumbnailUrl"] = this.thumbnailUrl;
    data["shortDescription"] = this.shortDescription;
    data["longDescription"] = this.longDescription;
    data["status"] = this.status;
    if (this.authors != null) data["authors"] = this.authors;
    if (this.categories != null) data["categories"] = this.categories;
    return data;
  


class PublishedDate 
  String? $date;

  PublishedDate(this.$date);

  PublishedDate.fromJson(Map<String, dynamic> json) 
    this.$date = json["$$date"];
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data["$$date"] = this.$date;
    return data;
  

【讨论】:

是的,该类 ID 需要在您的 JSON 文件中使用适当的数据类型进行更新。 @a-starck02 更新了int 修复的答案。 好的,现在我明白了。打算试试看。谢谢! 如果对您有帮助,请务必接受答案,谢谢!

以上是关于List<dynamic> 类型不是 Map<String dynamic> 类型的子类型的主要内容,如果未能解决你的问题,请参考以下文章

类型 List<dynamic> 不是类型 'Map<String, dynamic>' 的子类型

_TypeError(类型 'List<dynamic>' 不是类型 'Map<String, dynamic> 的子类型

未处理的异常:类型 'List<dynamic>' 不是类型 'Map<String, dynamic>' 的子类型

我得到一个 - 类型 'List<dynamic>' 不是类型 'Map<String, dynamic>' 的子类型错误

未处理的异常:类型 'List<dynamic>' 不是类型 'Map<String, dynamic

_TypeError(类型'List<dynamic>'不是'Map<String,dynamic>'类型的子类型)