You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter报错:type 'Null' is not a subtype of type 'int',多JSON解析失败

问题根源

你当前的代码是为解析单个Album对象编写的,但目标接口返回的是包含employees数组的JSON结构。直接用Album.fromJson解析整个返回结果时,因为找不到userId、id、title字段,会返回Null,而Album的属性是不可为null的int类型,因此触发type 'Null' is not a subtype of type 'int'错误。


完整解决方案

1. 定义匹配接口的员工数据模型

根据接口返回的员工结构,创建Employee类:

class Employee {
  final int id;
  final String name;
  final String position;
  final String department;

  Employee({
    required this.id,
    required this.name,
    required this.position,
    required this.department,
  });

  // 从JSON解析员工对象
  factory Employee.fromJson(Map<String, dynamic> json) {
    return Employee(
      id: json['id'] as int,
      name: json['name'] as String,
      position: json['position'] as String,
      department: json['department'] as String,
    );
  }
}

2. 修改数据获取方法

更新请求逻辑,解析接口中的employees数组:

Future<List<Employee>> fetchEmployees() async {
  final response = await http.get(
    Uri.parse('https://my-json-server.typicode.com/fluttirci/testJson/db'),
  );

  if (response.statusCode == 200) {
    Map<String, dynamic> data = jsonDecode(response.body);
    List<dynamic> employeesList = data['employees'];
    return employeesList.map((json) => Employee.fromJson(json)).toList();
  } else {
    throw Exception('加载员工数据失败');
  }
}

3. 用表格展示所有员工数据

替换原有UI代码,实现可横向滚动的表格:

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

// 插入Employee类和fetchEmployees方法

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

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late Future<List<Employee>> futureEmployees;

  @override
  void initState() {
    super.initState();
    futureEmployees = fetchEmployees();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '员工数据展示',
      theme: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('员工数据'),
        ),
        body: FutureBuilder<List<Employee>>(
          future: futureEmployees,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: DataTable(
                  columns: const [
                    DataColumn(label: Text('ID')),
                    DataColumn(label: Text('姓名')),
                    DataColumn(label: Text('职位')),
                    DataColumn(label: Text('部门')),
                  ],
                  rows: snapshot.data!.map((employee) {
                    return DataRow(cells: [
                      DataCell(Text(employee.id.toString())),
                      DataCell(Text(employee.name)),
                      DataCell(Text(employee.position)),
                      DataCell(Text(employee.department)),
                    ]);
                  }).toList(),
                ),
              );
            } else if (snapshot.hasError) {
              return Center(child: Text('${snapshot.error}'));
            }
            return const Center(child: CircularProgressIndicator());
          },
        ),
      ),
    );
  }
}

可选:网格布局展示

如果需要用网格卡片展示,替换FutureBuilder中的表格部分为以下代码:

return GridView.builder(
  padding: const EdgeInsets.all(8),
  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,
    crossAxisSpacing: 8,
    mainAxisSpacing: 8,
  ),
  itemCount: snapshot.data!.length,
  itemBuilder: (context, index) {
    Employee employee = snapshot.data![index];
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('ID: ${employee.id}'),
            const SizedBox(height: 8),
            Text('姓名: ${employee.name}', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
            const SizedBox(height: 4),
            Text('职位: ${employee.position}'),
            Text('部门: ${employee.department}'),
          ],
        ),
      ),
    );
  },
);

内容的提问来源于stack exchange,提问作者crag hack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:35:41