Flutter读取JSON时抛出FormatException: Unexpected end of input错误
Flutter JSON解析FormatException: Unexpected end of input 问题修复
问题现象
Flutter运行时抛出如下错误:
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: FormatException: Unexpected end of input (at character 88586) [ ] E/flutter ( 5286): ...820457458, -0.09168463200330734, 0.9341723918914795, 0.9910492897033691]}",
原有实现逻辑:
- 手动拼接字符串构造JSON片段,存入列表:
for(var i = 0 ; i <=32; ++i) { String entry = '{contents: [' '${contentList.content[i].x.toString()}, ' '${contentList.content[i].y.toString()}, ' '${contentList.content[i].z.toString()}, ' '${contentList.content[i].visibility.toString()}, ' '${contentList.content[i].presence.toString()}]}'; content_collector.add(entry); }
- 将字符串列表传入方法写入JSON文件:
Future<File> saveToJSONFile(List<String> contents_list, String filename) async { String encodedContents = jsonEncode(contents_list); Directory appDocDir = await getApplicationDocumentsDirectory(); String appDocPath = appDocDir.path + '/' + filename; return await File(appDocPath).writeAsString(encodedContents); }
- 读取文件并解析JSON:
void readJSON(String path) async { Directory appDocDir = await getApplicationDocumentsDirectory(); String appDocPath = appDocDir.path + '/' + path; String response = await File(appDocPath).readAsString(); final data = await json.decode(response.toString()); }
执行readJSON时抛出上述格式异常,手动排查未定位到原因。
错误原因
- 核心问题是手动拼接JSON字符串本身不符合JSON语法规范:标准JSON要求所有对象的键必须用双引号包裹,你拼接的
{contents: [xxx]}中contents未加双引号,属于非法JSON结构。 - 序列化逻辑存在矛盾:你将手动拼接的字符串存入列表后调用
jsonEncode,此时jsonEncode会把每个字符串当成普通文本值做转义处理,而非按JSON对象序列化,最终生成的文件是字符串数组而非预期的对象数组;如果拼接过程中数值转字符串出现特殊字符、或者文件写入未完全刷盘,就会出现内容截断,触发"输入意外结束"的解析错误。
修复方案
禁止手动拼接JSON字符串,所有JSON序列化操作直接交给内置jsonEncode方法处理,只需要传入结构化的Dart基础类型(Map、List、数字、字符串、布尔值、null)即可自动生成完全合规的JSON内容,从根源避免格式问题。
- 替换手动拼接字符串的逻辑,直接构造结构化数据列表:
// 初始化结构化列表,不需要存字符串 List<Map<String, List<num>>> content_collector = []; for(var i = 0 ; i <=32; ++i) { final item = contentList.content[i]; content_collector.add({ "contents": [ item.x, item.y, item.z, item.visibility, item.presence ] }); }
- 优化写入方法,增加刷盘参数避免大文件写入截断:
Future<File> saveToJSONFile(List<Map<String, List<num>>> contents_list, String filename) async { String encodedContents = jsonEncode(contents_list); Directory appDocDir = await getApplicationDocumentsDirectory(); String appDocPath = '${appDocDir.path}/$filename'; // flush: true 确保内容完全写入磁盘后再返回 return await File(appDocPath).writeAsString(encodedContents, flush: true); }
- 简化读取逻辑,移除多余的toString()调用:
void readJSON(String path) async { Directory appDocDir = await getApplicationDocumentsDirectory(); String appDocPath = '${appDocDir.path}/$path'; String response = await File(appDocPath).readAsString(); // 解析后直接得到结构化的List对象,可按需取值 final data = json.decode(response); }
内容的提问来源于stack exchange,提问作者mchd
相关产品推荐
相关产品推荐

