_TypeError(类型“_Map<String, dynamic>”不是类型“List<dynamic>”的子类型)

问题描述 投票:0回答:2

我正在尝试构建一个应用程序,以在身份验证后将 JSON 数据可视化到表中,这是我使用 http.dart 从 REST API 获取的数据

我制作了一个 home_screen.dart 来可视化它,但我遇到了这个错误

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'auth_service.dart';
import 'login_screen.dart';

class HomePage extends StatelessWidget {
  final AuthService _authService = AuthService();
  static const String apiUrl = 'my_api_url';

  HomePage({super.key});

  Future<List<Map<String, dynamic>>> fetchData() async {
    final token = await _authService.getToken();

    final response = await http.get(
      Uri.parse('$apiUrl/table'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
    );

    if (response.statusCode == 200) {
      final List<dynamic> data = jsonDecode(response.body);
      return List<Map<String, dynamic>>.from(data);
    } else {
      throw Exception('Failed to load data');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            FutureBuilder(
              future: fetchData(),
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  if (snapshot.hasError) {
                    return Text('Error: ${snapshot.error}');
                  } else {
                    List<Map<String, dynamic>> data =
                        snapshot.data as List<Map<String, dynamic>>;
                    return DataTable(
                      columns: const [
                        DataColumn(label: Text('ID')),
                        DataColumn(label: Text('Username')),
                        DataColumn(label: Text('Town')),
                        DataColumn(label: Text('Priority')),
                      ],
                      rows: data
                          .map(
                            (row) => DataRow(
                              cells: [
                                DataCell(Text(row['id'].toString())),
                                DataCell(Text(row['username'])),
                                DataCell(Text(row['town'])),
                                DataCell(Text(row['priority'])),
                              ],
                            ),
                          )
                          .toList(),
                    );
                  }
                } else {
                  return const CircularProgressIndicator();
                }
              },
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                await _authService.logout();
                Navigator.pushReplacement(
                  context,
                  MaterialPageRoute(builder: (context) => const LoginPage()),
                );
              },
              child: const Text('Logout'),
            ),
          ],
        ),
      ),
    );
  }
}

接下来是我得到的 JSON response.body 的示例(我只需要 id、城镇、用户名、优先级)

{
            "id": 104645,
            "area": {
                "id": 192,
                "depth": 4,
            },
            "workflow": {
                "id": 4,
                "name": "processing"
            },
            "state": {
                "id": 2,
                "name": "In work",
            },
            "workObject": {
                "type": "MeterPoint",
                "id": 427840,
                "consumingFacility": {
                    "id": 107303,
                    "address": {
                        "town": "New York"
                    },
                    "coordinates": null
                },
            },
            "assignee": {
                "id": 865,
                "fullName": "John Martins"
            },
            "coordinator": {
                "id": 804,
                "username": "sfr-es-martinsons",
            },
            "priority": 3
        }

你能帮我解决这个问题吗 我刚刚开始学习 dart,这个麻烦对我来说似乎无法解决

flutter dart http get
2个回答
0
投票

您的回报需要一个列表>,您需要使用地图功能。

 if (response.statusCode == 200) {
        final List<dynamic> responseData = jsonDecode(response.body);
        List<Map<String, dynamic>> data = responseData.map((item) {
          return {
            'id': item['id'],
            'town': item['workObject']['consumingFacility']['address']['town'],
            'username': item['coordinator']['username'],
            'priority': item['priority'],
          };
        }).toList();
    
        return data;
      } else {
        throw Exception('Failed to load data');
      }

0
投票

您遇到的错误 TypeError(类型“_Map”不是类型“List”的子类型)表明来自 API 的响应未得到正确处理。问题出在 fetchData 函数中,您尝试将 JSON 响应转换为地图列表。

让我们修改 fetchData 函数以正确处理响应的 JSON 结构。在您的示例 JSON 中,相关数据嵌套在各种键下。您需要从嵌套结构中提取必要的信息。具体方法如下:

Future<List<Map<String, dynamic>>> fetchData() async {
  final token = await _authService.getToken();

  final response = await http.get(
    Uri.parse('$apiUrl/table'),
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $token',
    },
  );

  if (response.statusCode == 200) {
    final List<dynamic> dataList = jsonDecode(response.body);

    // Extracting the relevant fields from the nested structure
    List<Map<String, dynamic>> data = dataList.map((item) {
      return {
        'id': item['id'],
        'username': item['coordinator']['username'],
        'town': item['workObject']['consumingFacility']['address']['town'],
        'priority': item['priority'],
      };
    }).toList();

    return data;
  } else {
    throw Exception('Failed to load data');
  }
}

在此修改中,我们迭代 dataList 中的每个项目并从嵌套结构中提取所需的字段。根据您的实际数据结构,根据需要调整字段名称。

此外,请确保API返回的数据符合您的期望。如果 API 响应结构发生变化,您可能需要相应更新数据提取逻辑。

这应该有助于解决您遇到的类型错误。

© www.soinside.com 2019 - 2024. All rights reserved.