类型“List<dynamic>”不是“Map<String”类型的子类型,在颤振应用中是动态的

Posted

技术标签:

【中文标题】类型“List<dynamic>”不是“Map<String”类型的子类型,在颤振应用中是动态的【英文标题】:type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic in flutter app 【发布时间】:2021-03-24 02:28:18 【问题描述】:

我正在尝试在 Flutter 中创建 API 请求,但我收到以下错误作为响应

类型 'List' 不是类型 'Map' 的子类型

我正在尝试创建第一个 API,如果方法合适,请告诉我

这是我的代码

import 'package:flutter/material.dart';

class Product 
  final int id;
  final String title, description;
  final String images;
  final List<Color> colors;
  final double price;
  final double rating;
  final bool isFavourite, isPopular;

  Product(
      this.id,
      this.images,
      this.colors,
      this.title,
      this.price,
      this.rating,
      this.description,
      this.isFavourite,
      this.isPopular);
  factory Product.fromJson(Map<String, dynamic> json) 
    return Product(
      id: json['id'],
      images: json['images'],
      title: json['title'],
      price: json['price'],
      rating: json['rating'],
      description: json['description'],
    );
  



Future<Product> fetchProd() async 
  final response = await http.get('https://test.com/sampleapi.php');

  if (response.statusCode == 200) 
    // If the server did return a 200 OK response,
    // then parse the JSON.
    return Product.fromJson(jsonDecode(response.body));
   else 
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  


class ProdList extends StatefulWidget 
  @override
  _ProdListState createState() => _ProdListState();


class _ProdListState extends State<ProdList> 
  Future<Product> futureProdLists;
  @override
  void initState() 
    super.initState();
    futureProdLists = fetchProd();
  
  

 

  @override
  Widget build(BuildContext context) 
    return Column(children: [
      Padding(
        padding:
            EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(20)),
        child: SectionTitle(title: "Popular Products", press: () ),
      ),
      SizedBox(height: getProportionateScreenWidth(20)),
      SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: FutureBuilder<Product>(
          future: futureProdLists,
          builder: (context, snapshot) 
            print(snapshot);
            if (snapshot.hasData) 
              return Text(snapshot.data.title);
             else if (snapshot.hasError) 
              return Text("$snapshot.error");
            

这是我的示例 API

[
  
    "id": "0001",
    "images": "assets/images/ps4_console_white_1.png",
    "title": "Wireless Controller for PS4",
    "price": 25,
    "description": "description",
    "rating": 4.8,
    "rating (copy)": 4.8,
    "isFavourite": true,
    "isPopular": true
  ,
  
    "id": "0001",
    "images": "assets/images/ps4_console_white_1.png",
    "title": "Wireless Controller for PS4",
    "price": 25,
    "description": "description",
    "rating": 4.8,
    "rating (copy)": 4.8,
    "isFavourite": true,
    "isPopular": true
  ,
  
    "id": "0001",
    "images": "assets/images/ps4_console_white_1.png",
    "title": "Wireless Controller for PS4",
    "price": 25,
    "description": "description",
    "rating": 4.8,
    "rating (copy)": 4.8,
    "isFavourite": true,
    "isPopular": true
  ,
  
    "id": "0001",
    "images": "assets/images/ps4_console_white_1.png",
    "title": "Wireless Controller for PS4",
    "price": 25,
    "description": "description",
    "rating": 4.8,
    "rating (copy)": 4.8,
    "isFavourite": true,
    "isPopular": true
  ,
  
    "id": "0001",
    "images": "assets/images/ps4_console_white_1.png",
    "title": "Wireless Controller for PS4",
    "price": 25,
    "description": "description",
    "rating": 4.8,
    "rating (copy)": 4.8,
    "isFavourite": true,
    "isPopular": true
  
]

【问题讨论】:

【参考方案1】:

这肯定会奏效。 final Product product = productFromJson(jsonString);


import 'dart:convert';

List<Product> productFromJson(String str) => List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));

String productToJson(List<Product> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Product 
    Product(
        this.id,
        this.images,
        this.title,
        this.price,
        this.description,
        this.rating,
        this.ratingCopy,
        this.isFavourite,
        this.isPopular,
    );

    String id;
    String images;
    String title;
    int price;
    String description;
    double rating;
    double ratingCopy;
    bool isFavourite;
    bool isPopular;

    factory Product.fromJson(Map<String, dynamic> json) => Product(
        id: json["id"],
        images: json["images"],
        title: json["title"],
        price: json["price"],
        description: json["description"],
        rating: json["rating"].toDouble(),
        ratingCopy: json["rating (copy)"].toDouble(),
        isFavourite: json["isFavourite"],
        isPopular: json["isPopular"],
    );

    Map<String, dynamic> toJson() => 
        "id": id,
        "images": images,
        "title": title,
        "price": price,
        "description": description,
        "rating": rating,
        "rating (copy)": ratingCopy,
        "isFavourite": isFavourite,
        "isPopular": isPopular,
    ;

【讨论】:

【参考方案2】:

问题是您的api 响应为您提供了产品对象的json 数组,而您正试图将数组转换为产品对象,这就是问题所在。

现在您必须迭代 json 数组并将每个元素转换为 Product 对象并将它们存储在一个列表中。

用下面的代码 sn-p 替换您的 fetchProd 方法。

Future<List<Product>> fetchProd() async 
  List<Product> prodList = [];

  final response = await http.get('https://test.com/sampleapi.php');

  if (response.statusCode == 200) 
    // If the server did return a 200 OK response,
    // then parse the JSON.
    var jsonList = jsonDecode(response.body);
    for(var prod in jsonList)
      prodList.add(Product.fromJson(prod));
    
    return prodList;
   else 
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  

【讨论】:

无法从函数“fetchProd”返回类型为“List”的值,因为它的返回类型为“Future”。dartreturn_of_invalid_type 作为@Saiful Islam,它的 API 返回 JSON 数组而不是 json 对象,因此是 List 而不是 Map。 我更新了代码,现在就试试吧。 @vellai durai【参考方案3】:

试试这个

Future<Product> fetchProd() async 
  final response = await http.get('https://test.com/sampleapi.php');

  if (response.statusCode == 200) 
    // If the server did return a 200 OK response,
    // then parse the JSON.
    return (response.body as List)
      .map((item) => Product.fromJson(item))
      .toList();
   else 
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  

【讨论】:

以上是关于类型“List<dynamic>”不是“Map<String”类型的子类型,在颤振应用中是动态的的主要内容,如果未能解决你的问题,请参考以下文章

类型 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>'类型的子类型)