indexeddb 存储可序列化的 javascript 对象而非 json 字符串,需将嵌套字段拍平为顶层属性以支持索引;避免 undefined、nan、null 值导致索引失效;禁用 stringify 后的字符串存储;原始 json 可作为辅助字段按需保留。

IndexedDB 本身不存 JSON 字符串,而是存可序列化的 JavaScript 对象。把 JSON 数据“映射”进 IndexedDB,核心不是格式转换,而是结构适配——要让字段可索引、可查询、可增量更新。
字段必须拍平,不能保留嵌套路径
IndexedDB 的索引只支持顶层属性,不识别 user.profile.city 这类点号路径。原始 JSON 中的嵌套结构必须提前展开:
- 把
{"user": {"name": "Alice", "profile": {"city": "Shanghai"}}转为{"user_name": "Alice", "user_profile_city": "Shanghai"} - 所有待索引字段(如用于筛选、排序的)都得是对象的直接属性
- 深层字段若不常查,可压缩进一个
metadata字段(仍为字符串或对象),但不可用于createIndex()
索引字段值必须合法且稳定
字段值为 undefined、NaN 或 null 时,对应索引条目会缺失或失效,导致查询漏数据:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 写入前做基础校验:用
Number.isFinite()检查数值,用typeof === 'string' && str.length检查字符串 - 空数组、空对象可保留;但避免用
{}或[]替代缺失字段——统一用null或剔除该键 - 时间字段优先用毫秒数(
Date.now()),而非Date实例(虽支持,但跨浏览器序列化行为略异)
别存 JSON.stringify() 后的字符串
把整个 JSON stringify 后当 value 存,等于放弃 IndexedDB 的全部优势:
- 索引无法命中,后续所有查询都退化为
openCursor()全表遍历 +JSON.parse()+ JS 过滤 - 单条记录体积膨胀(双引号、转义符、缩进等冗余字符)
- 正确做法是传原生对象:
store.put({ id: 'cfg-1', category: 'ui', enabled: true })
原始 JSON 可作为辅助字段保留
如果业务需要完整原始结构(比如导出、回滚、调试),可以额外存一份压缩后的原始数据:
- 新增字段如
raw_data,类型为Uint8Array(gzip 压缩后)或短字符串(仅 base64 小数据) - 主查询逻辑永远基于结构化字段,
raw_data仅在点击详情、导出、水合时按需解析 - 避免在游标遍历中反复调用
JSON.parse(raw_data),那会立刻卡主线程










