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

如何将含JSON字符串的JSON列表写入.json文件并实现读取与反序列化?

问题分析与修复方案

你的代码存在几个核心问题导致读写逻辑失效:

  • readHistory在文件不存在时返回[''],会让后续逻辑误判为已有内容,且属于无效JSON结构
  • writeHistory对readHistory返回的结果重复执行jsonDecode,会抛出解码错误(因为readHistory已经返回了解码后的列表)
  • 错误地将map转为JSON字符串再存入列表,导致文件存储的是字符串数组而非对象数组,后续遍历还要额外解码,完全冗余

修改后的代码

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

// 保持原有文件获取逻辑,这里补充完整示例
Future<File> get _localFile async {
  final directory = await getApplicationDocumentsDirectory();
  return File('${directory.path}/history.json');
}

Future writeHistory(Map<String, dynamic>? map) async {
  if (map == null) return; // 空map直接返回,避免写入无效数据
  final file = await _localFile;
  // 读取已有的历史列表,空文件或不存在时返回空列表
  final List<dynamic> infoList = await readHistory();
  // 直接将map添加到列表,无需转字符串
  infoList.add(map);
  // 将整个列表序列化为JSON字符串写入文件
  return file.writeAsString(convert.jsonEncode(infoList), mode: FileMode.write);
}

Future<List<dynamic>> readHistory() async {
  try {
    final file = await _localFile;
    if (!await file.exists()) return []; // 文件不存在返回空列表
    final contents = await file.readAsString();
    if (contents.isEmpty) return []; // 文件为空返回空列表
    // 解码为列表,确保是数组结构
    final decoded = convert.jsonDecode(contents);
    return decoded is List ? decoded : [];
  } catch (e) {
    // 解码失败或其他异常统一返回空列表
    return [];
  }
}

读取并遍历的示例

void loadAndTraverseHistory() async {
  final List<dynamic> historyList = await readHistory();
  for (var item in historyList) {
    // 转为Map类型后使用
    Map<String, dynamic> historyItem = item as Map<String, dynamic>;
    // 这里处理每个历史项,比如打印内容
    print(historyItem);
  }
}

关键修复说明

  1. 初始状态修正:文件不存在或为空时返回空列表,避免无效数据干扰后续逻辑
  2. 简化编码解码流程:直接操作Map对象组成的列表,写入时整体转JSON,读取时直接得到对象列表
  3. 空值防护:写入前先判断传入的map是否为空,防止写入null
  4. 类型安全校验:读取时校验解码结果是否为列表,避免类型转换错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:01:28