【问题标题】:type List<dynamic> is not a subtype of Map<String,dynamic>类型 List<dynamic> 不是 Map<String,dynamic> 的子类型
【发布时间】:2020-09-02 06:00:33
【问题描述】:

我已经能够学习一些关于 Flutter 的关于基本 UI 设计的教程,并且是 API 调用的新手。我想我需要在进行 API 调用后转换类型,但我不知道如何。

注意:我知道这是一个文件中有很多代码,但我会将 API 调用文件和自定义类文件与我的主文件分开

import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

Future<Country> fetchAlbum() async {
  final response = await http.get('https://restcountries.eu/rest/v2/all');

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

class Country {
  final String name;
  final List<String> topLevelDomain;
  final String alpha2Code;
  final String alpha3Code;
  final String callingCodes;
  final String capital;
  final String region;
  final String subregion;
  final int population;
  final List<int> latlng;
  final String demonym;
  final int area;
  final int gini;
  final List<String> timezones;
  final List<String> borders;
  final String nativeName;
  final int numericCode;
  final List<String> currencies;
  final List<String> translations;
  final String flag;
  final String cioc;

  Country({
    @required this.name,
    @required this.topLevelDomain,
    @required this.alpha2Code,
    @required this.alpha3Code,
    @required this.callingCodes,
    @required this.capital,
    @required this.region,
    @required this.subregion,
    @required this.population,
    @required this.latlng,
    @required this.demonym,
    @required this.area,
    @required this.gini,
    @required this.timezones,
    @required this.borders,
    @required this.nativeName,
    @required this.numericCode,
    @required this.currencies,
    @required this.translations,
    @required this.flag,
    @required this.cioc,
  });

  factory Country.fromJson(Map<String, dynamic> json) {
    return Country(
      name: json['name'],
      topLevelDomain: json['topLevelDomain'],
      alpha2Code: json['alpha2Code'],
      alpha3Code: json['alpha3Code'],
      callingCodes: json['callingCodes'],
      capital: json['capital'],
      region: json['region'],
      subregion: json['subregion'],
      population: json['population'],
      latlng: json['latlng'],
      demonym: json['demonym'],
      area: json['area'],
      gini: json['gini'],
      timezones: json['timezones'],
      borders: json['borders'],
      nativeName: json['nativeName'],
      numericCode: json['numericCode'],
      currencies: json['currencies'],
      translations: json['translations'],
      flag: json['flag'],
      cioc: json['cioc'],
    );
  }
}

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Future<Country> futureAlbum;

  @override
  void initState() {
    super.initState();
    futureAlbum = fetchAlbum();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fetch Data Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Fetch Data Example'),
        ),
        body: Center(
          child: FutureBuilder<Country>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data.name);
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              }

              // By default, show a loading spinner.
              return CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

这是我的模拟器屏幕的样子:http://i1.imgrr.com/18Z/7512_Screenshot1599026660.png

【问题讨论】:

  • 尝试使用factory Country.fromJson(Map&lt;dynamic, dynamic&gt; json)
  • type List 不是 Map 的 sybtype
  • 尝试使用工厂 Country.fromJson(dynamic json)

标签: android flutter dart mobile-development


【解决方案1】:

第 12 行'return Country.fromJson(json.decode(response.body));'

我认为'json.decode(response.body)'的类型是'List',但参数类型在这里是Map。也许您的响应是 Country 对象列表,但它返回 1 Country 对象。这就是你得到这个错误的原因

【讨论】:

  • 大概就是这样;我该怎么做才能改变返回类型?
  • 这取决于你。该 API 返回一个列表。所以你可以先获取列表,运行循环并将每个元素(类型为 Map)转换为你的对象,然后做你想做的事
  • 我是 Flutter 新手;你能把代码写出来给我解释一下吗?
  • Future&lt;List&gt; fetchAlbum() async { final response = await http.get('https://restcountries.eu/rest/v2/all'); if (response.statusCode == 200) { // If the server did return a 200 OK response, // then parse the JSON. List list = []; json.decode(response.body).forEach((e) =&gt; list.add(Country.fromJson(e)) ); return list; } else { // If the server did not return a 200 OK response, // then throw an exception. throw Exception('Failed to load album'); } }
  • 如果您想使用国家/地区列表,您必须更改函数 return Future。或仅返回您要使用的 1 个国家/地区
【解决方案2】:

您的 API 返回 List 而不是 Map

您需要将每个元素映射为Country

Future<List<Country>> fetchAlbum() async {
  final response = await http.get('https://restcountries.eu/rest/v2/all');

  if (response.statusCode == 200) {
     List<Country> countryList = ((json.decode(response.body) as List).map((i) => Country.fromJson(i)).toList();
    return countryList;
  } else {
    throw Exception('Failed to load album');
  }
}

【讨论】:

猜你喜欢
  • 2021-12-29
  • 2023-01-08
  • 2019-04-03
  • 2021-10-25
  • 2020-07-03
  • 2019-12-05
  • 2023-03-11
  • 1970-01-01
  • 2021-09-12
相关资源
最近更新 更多