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

Flutter调用Beeceptor接口时遇类型转换异常求助

解决Dart中"null is not a subtype of String of type cast"类型转换异常

问题描述

使用Beeceptor创建Web服务后,调用接口更新UI时抛出**"null is not a subtype of String of type cast"**类型转换异常,无法正常加载数据。

API返回数据格式

当前Beeceptor返回的JSON结构如下:

[
  {
    "0":{
      "name":"Emmanuel Armoo",
      "imageUrl":"https://www.pexels.com/photo/man-smiling-behind-wall-220453/",
      "time":"2:00",
      "description":"The is an ancient geek priest who discovered the whole fact to unlease the new technological advancement"
    },
    "1":{
      "name":"Emmanuel Armoo",
      "imageUrl":"https://www.pexels.com/photo/man-smiling-behind-wall-220453/",
      "time":"2:00",
      "description":"The is an ancient geek priest who discovered the whole fact to unlease the new technological advancement"
    },
    "3":{
      "name":"Sister Armoo",
      "imageUrl":"https://www.pexels.com/photo/man-smiling-behind-wall-220453/",
      "time":"2:00",
      "description":"The is an ancient geek priest who discovered the whole fact to unlease the new technological advancement"
    },
    "4":{
      "name":"Kofi Armoo",
      "imageUrl":"https://www.pexels.com/photo/man-smiling-behind-wall-220453/",
      "time":"2:00",
      "description":"The is an ancient geek priest who discovered the whole fact to unlease the new technological advancement"
    }
  }
]

相关代码

User类代码

import 'package:my_api_practice/Endpoint/endpoint.dart';
import 'dart:convert';
import 'package:http/http.dart'as http;

import 'UserDetails.dart';
import '';
part 'User.g.dart';

class User{
  String? name;
  String? imageUrl;
  String? time;
  List<UserDetails>?details;

  User({required this.details,required this.name,required this.imageUrl,required this.time});

  factory User.fromJson(Map<String,dynamic>json)=>_$UserFromJson(json);

  User.blank()
  :name='',
  imageUrl='',
  time='',
  details=[];

  static Future <List<User>>firstApi()async{
    http.Response response=await http.get(Uri.parse("https://xcompany.free.beeceptor.com/api/v1/users"));

    List<User>jsonitem=[];

    if(response.statusCode!=200){
      print(response.body);
    }
    for(var newItems in json.decode(response.body)){
      jsonitem.add(User.fromJson(newItems));
    }

    return jsonitem;
  }
}

UI代码

import 'package:my_api_practice/models/User.dart';
import 'package:flutter/material.dart';

class UserList extends StatefulWidget{
  createState()=>_UserList();
}
class _UserList extends State<UserList> {
  bool isWaiting = false;
  List<User>users = [];


  void initState(){
    super.initState();
    ApiData();
  }
  ApiData() async {
    isWaiting=true;
    var jsonItem = await User.firstApi();
    setState(() {
      users = jsonItem;
      isWaiting=false;
    });
  }

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('UserList'),
      ),
      body: Column(
        children: [
          isWaiting ? LinearProgressIndicator(
            value: null,
            backgroundColor: Colors.grey,
            valueColor: AlwaysStoppedAnimation<Color>(Colors.black),
          ) : Container(
            child:Text('No UI to load')
          ),
          Expanded(
              child: ListView.builder(
                itemCount: users.length,
                itemBuilder: _itemTiles,)

          )
        ],
      ),
    );
  }

  Widget _itemTiles(BuildContext context, int index) {
    return ListTile(
      leading: _listImages(context, this.users[index]),
      title: _listTitles(context, this.users[index]),
      trailing: _listTimes(context, this.users[index]),
    );
  }

  Widget _listImages(BuildContext context, User user) {
    return ClipRRect(
        borderRadius: BorderRadius.all(Radius.circular(30)),
        child: Image.network(user.imageUrl!)
    );
  }

  Widget _listTitles(BuildContext context, User user) {
    return Text(user.name!);
  }


  Widget _listTimes(BuildContext context, User user) {
    return Text(user.time!);
  }

}

问题分析

  1. API结构与代码预期不匹配:代码期望返回User对象的数组,但实际API返回的是包含单个对象的数组,该对象以索引字符串("0"、"1"等)为键,值才是用户数据。直接遍历外层数组会把整个索引对象当成User的JSON解析,导致字段不匹配。
  2. User类字段与API返回不一致:User类定义了details字段,但API返回中没有该字段,反而存在description字段,序列化时会因找不到对应字段触发null类型转换错误。
  3. 空安全处理不当:UI代码中直接用!强制解包nullable字段,若API返回字段为null会触发异常。

解决方案

方案1:修正API返回格式(推荐)

修改Beeceptor的响应,直接返回User对象的数组,格式如下:

[
  {
    "name":"Emmanuel Armoo",
    "imageUrl":"https://www.pexels.com/photo/man-smiling-behind-wall-220453/",
    "time":"2:00",
    "description":"xxx"
  },
  {
    "name":"Sister Armoo",
    "imageUrl":"https://www.pexels.com/photo/man-smiling-behind-wall-220453/",
    "time":"2:00",
    "description":"xxx"
  }
]

方案2:适配现有API格式修改代码

如果无法修改API格式,调整解析逻辑和User类:

  1. 修改firstApi方法的解析逻辑:
static Future<List<User>> firstApi()async{
  http.Response response=await http.get(Uri.parse("https://xcompany.free.beeceptor.com/api/v1/users"));

  List<User> jsonitem=[];

  if(response.statusCode!=200){
    print(response.body);
  }
  // 解析外层数组,取出包含用户的对象
  var outerArray = json.decode(response.body) as List;
  if(outerArray.isNotEmpty){
    var userMap = outerArray[0] as Map<String, dynamic>;
    // 遍历对象的values获取每个用户数据
    for(var newItems in userMap.values){
      jsonitem.add(User.fromJson(newItems));
    }
  }

  return jsonitem;
}
  1. 修正User类字段:
class User{
  String? name;
  String? imageUrl;
  String? time;
  String? description; // 替换details为API返回的description字段

  // 调整构造函数参数
  User({required this.description, required this.name, required this.imageUrl, required this.time});

  factory User.fromJson(Map<String,dynamic>json)=>_$UserFromJson(json);

  User.blank()
      :name='',
      imageUrl='',
      time='',
      description=''; // 同步修改空白构造函数
}

修改后重新运行flutter pub run build_runner build生成新的序列化代码。

  1. 优化UI的空安全处理:
Widget _listImages(BuildContext context, User user) {
  return ClipRRect(
      borderRadius: BorderRadius.all(Radius.circular(30)),
      child: Image.network(user.imageUrl ?? 'https://默认图片地址')
  );
}

Widget _listTitles(BuildContext context, User user) {
  return Text(user.name ?? '未知名称');
}

Widget _listTimes(BuildContext context, User user) {
  return Text(user.time ?? '未知时间');
}

内容的提问来源于stack exchange,提问作者Emmanuel Armoo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:35:17