Flutter解码大JSON时随机出现FormatException的排查求助
Flutter JSON解码随机触发FormatException问题
问题现象
- JSON解码时随机抛出FormatException,错误提示多为缺失引号、冒号、逗号或闭合括号,异常集中在JSON末尾
- JSON体积≥100KB时开始出现,≥300KB时几乎必现,<100KB也偶发
- 后端Laravel API经Postman测试返回正常,仅在模拟器中触发异常
- 已尝试更换Dio/Http库、切换http/https、设置ResponseType.plain、正则处理返回数据,均未解决
Http工具类代码
import 'dart:convert'; import 'package:http/http.dart' as http; class Http { Http._internal(); static final Http _instance = Http._internal(); Map<String, String> headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', }; String baseUrl = 'http://ipv4/api'; factory Http() { return _instance; } Future<http.Response> get( String path, { Map<String, dynamic>? queryParameters, Map<String, String>? customHeaders, }) async { final Uri uri = Uri.parse('$baseUrl$path').replace(queryParameters: queryParameters); final response = await http.get( uri, headers: {...headers, ...?customHeaders}, ); return response; } }
业务解码代码
final token = await _tokenFuture; final response = await Http().get('/construction', customHeaders: {'Authorization': 'Bearer $token'}); final List<Map<String, dynamic>> jsonList = List<Map<String, dynamic>>.from(json.decode(response.body));
异常示例
- 键缺失引号:
...material":"15000","labor:"10000"... - 值缺失引号:
...material":"15000","labor":10000"... - 缺失逗号:
...material":"15000""labor":"10000"... - 缺失冒号:
...material""15000","labor":"10000"... - 缺失闭合括号(暂未确认是否会在中间缺失)
解决方案建议
- 检查响应完整性
打印response.body.length并和后端实际返回的JSON长度对比,确认是否存在响应截断。模拟器网络环境可能存在分片传输时的拼接错误,导致JSON不完整。 - 强制指定UTF-8编码解析
后端返回的JSON可能存在编码不一致问题,手动指定编码避免解析异常:final responseBody = utf8.decode(response.bodyBytes); final jsonList = List<Map<String, dynamic>>.from(json.decode(responseBody)); - 启用Gzip压缩
大体积JSON开启压缩可减少传输数据量,降低截断概率:- 后端Laravel通过Nginx或中间件配置Gzip压缩
- Flutter请求头添加
Accept-Encoding: gzip,接收时解压:import 'dart:io'; Future<String> _decodeResponse(http.Response response) async { if (response.headers['content-encoding'] == 'gzip') { final gzipBytes = GZipCodec().decode(response.bodyBytes); return utf8.decode(gzipBytes); } return utf8.decode(response.bodyBytes); }
- 验证JSON合法性
解码前用工具验证JSON格式,或捕获异常后保存错误响应内容到本地,对比后端正确返回的JSON,定位具体截断或篡改位置。 - 检查模拟器网络代理
若模拟器开启了代理工具(如Charles),可能存在代理对大体积响应的篡改或截断,尝试关闭代理后测试。
内容的提问来源于stack exchange,提问作者Felipe
相关产品推荐
相关产品推荐

