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

Flutter读取JSON文件抛出FormatException异常的问题排查

Flutter异步读取JSON文件报错排查与修复

问题原代码

void readJSON(String path) async {
    
    Directory appDocDir = await getApplicationDocumentsDirectory();
    String appDocPath = appDocDir.path + '/' + path;
    print('Trying to read json file from ' + appDocPath);
    
    final Future<String> response = File(appDocPath).readAsString();
    final data = await json.decode(response.toString());
    final coordinates = await (data['elements'] as List).cast<double>();
    
    for(int i = 0; i <= coordinates.length; ++i){
      print(i);
    }
  }

运行时抛出两类异常:一类是FormatException,提示第1个字符位置存在意外字符,错误输出为Instance of 'Future<String>';另一类是类型不匹配异常,提示String类型无法作为int类型索引。

代码存在的具体错误

  • 未等待文件读取异步任务完成:File.readAsString()返回Future<String>类型,代码中没有加await等待结果返回,直接对Future实例调用toString()拿到的是固定字符串Instance of 'Future<String>',并非文件实际内容。将该字符串传入json.decode()时,由于内容不符合JSON格式,直接触发FormatException,和报错日志中第一个字符位置异常的描述完全匹配。
  • 无意义的异步等待导致类型错误:List.cast<double>()是内存中的同步类型转换操作,不存在异步逻辑,额外加await属于错误用法,会导致后续访问列表时触发类型匹配异常,对应日志中String无法作为int类型索引的报错。
  • 循环边界设置错误:for循环终止条件写为i <= coordinates.length,而Dart中List的合法索引范围是0到length - 1,当i等于length时会触发索引越界异常;且循环内仅打印索引值,没有打印对应元素内容,无法达到查看数据结构的目的。
  • 异步函数返回值类型不规范:标记为async的函数如果无返回值,应当声明返回类型为Future<void>,写为void会导致调用方无法正确等待异步任务执行完成,容易出现未捕获的异步异常。

修复后代码

import 'dart:convert';
import 'dart:io';
import 'package:path_provider/path_provider.dart';

// 修正异步函数返回值类型
Future<void> readJSON(String path) async {
  Directory appDocDir = await getApplicationDocumentsDirectory();
  // 使用字符串模板拼接路径,避免手动拼接分隔符出错
  String appDocPath = '${appDocDir.path}/$path';
  print('Trying to read json file from $appDocPath');

  // 加await等待文件读取完成,拿到真实的文件内容字符串
  final String fileContent = await File(appDocPath).readAsString();
  // 传入真实文件内容解析JSON,json.decode本身是同步方法不需要额外await
  final data = json.decode(fileContent);
  // 去掉cast操作前多余的await,同步完成类型转换
  final List<double> coordinates = (data['elements'] as List).cast<double>();

  // 修正循环边界为i < length,同时打印索引和对应元素值,方便查看数据结构
  for(int i = 0; i < coordinates.length; ++i){
    print('index: $i, value: ${coordinates[i]}');
  }
}

补充建议

  • 可以引入path包的join方法拼接路径,自动适配不同操作系统的路径分隔符,避免硬编码/带来的兼容性问题。
  • 建议为文件读取、JSON解析逻辑添加try-catch异常捕获,处理文件不存在、JSON格式不合法、字段类型不匹配等边界场景,避免程序直接崩溃。
  • 如果JSON中elements字段下的元素不是num类型,直接调用cast<double>()会触发类型转换异常,需要根据实际JSON结构调整解析逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:45:15