# JSON

## Description

JSON 模块提供围绕 JSON（JavaScript Object Notation）这一数据表示格式的相关基础能力，用于承载与 JSON 本身直接相关、且值得长期稳定维护的公共语义。

当前模块公开能力还很少，暂时只有 `repair` 这一项文本修复入口；但这不意味着模块边界仅限于修复本身，而是说明 JSON 相关能力仍在逐步沉淀中。

## For Understanding

理解 JSON 模块时，应把它看作一个围绕 JSON 本身建立的问题域模块，而不是一个泛化的数据清洗工具箱，也不是任意对象处理逻辑的收纳处。判断某项能力是否应进入这里，关键不在于它“碰巧输入或输出了 JSON”，而在于它是否直接服务于 JSON 这一表示格式本身的稳定语义。

这类能力通常可能包括 JSON 文本修复、序列化与反序列化辅助、稳定格式化、合法性判断、边界明确的表示转换，或其它直接围绕 JSON 文本与 JSON 语义展开的基础能力。当前仓库里之所以只有 `repair`，只是因为模块还处在较早阶段，而不是因为其它 JSON 相关能力天然不属于这里。

当前边界可以概括为：

- 它可以承载与 JSON 本身直接相关的公共能力，而不局限于当前已经存在的 `repair`。
- 它关注的是 JSON 作为表示格式时的稳定语义，而不是解析后对象在业务上的含义。
- 它可以处理文本层问题，也可以在未来扩展到仍然属于 JSON 语义边界内的其它能力。
- 它不应因为名称宽泛就退化成杂项对象工具箱或通用数据清洗工具箱。

因此，这个模块不应承载对象结构校验、字段语义补全、领域模型迁移、容错合并或业务级默认值推导。那些问题可能发生在 JSON 之前或之后，也可能依赖 JSON 作为载体，但并不因此自动属于 JSON 模块。

## For Using

当你需要复用一类与 JSON 本身直接相关的基础能力，而不是在业务代码里零散处理 JSON 文本、解析入口或表示细节时，可以使用这个模块。当前最直接的使用场景，是在解析之前先修复接近 JSON、但带有轻微格式噪声的文本，例如人工编辑配置、LLM 输出、宽松的第三方接口返回、日志片段复制结果，或历史遗留系统吐出的近似 JSON 文本。

当前公共能力可以从使用意图上理解为一类入口：

- 文本修复入口：把接近 JSON 的字符串整理成可继续交给标准解析器处理的 JSON 文本。

随着模块扩展，未来也可以继续容纳其它直接服务于 JSON 语义的公共入口。但即便如此，使用时仍应区分“JSON 本身的问题”和“业务对象的问题”：如果你的问题已经变成对象级校验、字段默认值注入、结构迁移或业务容错，那么应在其它模块或上层流程中继续分层，而不要把这些职责压回 JSON 模块。

## For Contributing

贡献 JSON 模块时，应优先判断新增能力是否直接表达 JSON 本身的稳定语义，而不是借着 JSON 的名字引入对象级处理、业务级清洗或协议级解释逻辑。这个模块可以继续增长，但增长方向应围绕 JSON 自身的问题域展开，而不是因为名字宽泛就无限吸纳一切与对象或文本有关的工具。

在扩展时，应优先遵守以下边界：

- 公共能力应直接围绕 JSON 本身展开，例如表示修复、合法性处理、稳定序列化或其它明确属于 JSON 语义的能力。
- 不要把 schema 校验、字段补全、结构迁移、业务默认值或容错合并直接写成 JSON 模块的公共职责。
- 若新增能力只是“使用了 JSON”但核心问题并不属于 JSON 本身，则应放在更合适的模块，而不是为了归类方便塞进这里。
- 对于像 `repair` 这类带有容错性质的能力，应保持失败语义清楚；当输入不能被稳定处理时，抛错通常比返回含糊结果更符合模块边界。

### JSDoc 注释格式要求

- 每个公开导出的目标（类型、函数、变量、类等）都应包含 JSDoc 注释，让人在不跳转实现的情况下就能理解用途。
- JSDoc 注释第一行应为清晰且简洁的描述，该描述优先使用中文（英文也可以）。
- 如果描述后还有其他内容，应在描述后加一个空行。
- 如果有示例，应使用 `@example` 标签，后接三重反引号代码块（不带语言标识）。
- 如果有示例，应包含多个场景，展示不同用法，尤其要覆盖常见组合方式或边界输入。
- 如果有示例，应使用注释格式说明每个场景：`// Expect: <result>`。
- 如果有示例，应将结果赋值给 `example1`、`example2` 之类的变量，以保持示例易读。
- 如果有示例，`// Expect: <result>` 应该位于 `example1`、`example2` 之前，以保持示例的逻辑清晰。
- 如果有示例，应优先使用确定性示例；避免断言精确的随机输出。
- 如果函数返回结构化字符串，应展示其预期格式特征。
- 如果有参考资料，应将 `@see` 放在 `@example` 代码块之后，并用一个空行分隔。

### 实现规范要求

- 不同程序元素之间使用一个空行分隔，保持结构清楚。这里的程序元素，通常指函数、类型、常量，以及直接服务于它们的辅助元素。
- 某程序元素独占的辅助元素与该程序元素本身视为一个整体，不要在它们之间添加空行。
- 程序元素的辅助元素应该放置在该程序元素的上方，以保持阅读时的逻辑顺序。
- 若辅助元素被多个程序元素共享，则应将其视为独立的程序元素，放在这些程序元素中第一个相关目标的上方，并与后续程序元素之间保留一个空行。
- 辅助元素也应该像其它程序元素一样，保持清晰的命名和适当的注释，以便在需要阅读实现细节时能够快速理解它们的作用和使用方式。
- 辅助元素的命名必须以前缀 `internal` 开头（或 `Internal`，大小写不敏感）。
- 辅助元素永远不要公开导出。
- 被模块内多个不同文件中的程序元素共享的辅助元素，应该放在一个单独的文件中，例如 `./src/json/internal.ts`；若当前模块仍然很小，则不必为了形式拆出没有稳定价值的共享文件。
- 模块内可以包含子模块。只有当某个子目录表达一个稳定、可单独理解、且可能被父模块重导出的子问题域时，才应将其视为子模块。
- 子模块包含多个文件时，应该为其单独创建子文件夹，并为其创建单独的 Barrel 文件；父模块的 Barrel 文件再重导出子模块的 Barrel 文件。
- 子模块不需要有自己的 `README.md`。
- 子模块可以有自己的 `internal.ts` 文件，多个子模块共享的辅助元素应该放在父模块的 `internal.ts` 文件中，单个子模块共享的辅助元素应该放在该子模块的 `internal.ts` 文件中。
- 对模块依赖关系的要求（通常是不循环依赖或不反向依赖）与对 DRY 的要求可能产生冲突。此时，若复用的代码数量不大，可以适当牺牲 DRY，复制粘贴并保留必要的注释说明；若复用的代码数量较大，则可以将其抽象到新的文件或子模块中，如 `common.ts`，并在需要的地方导入使用。
- 实现时应优先保持输入、输出与失败条件的语义清楚；若某项能力具有容错或修复性质，不应为了支持更多特例不断堆叠难以解释的隐式规则。

### 导出策略要求

- 保持内部辅助项和内部符号为私有，不要让外部接入依赖临时性的内部结构。
- 每个模块都应有一个用于重导出所有公共 API 的 Barrel 文件。
- Barrel 文件应命名为 `index.ts`，放在模块目录根部，并且所有公共 API 都应从该文件导出。
- 新增公共能力时，应优先检查它是否表达稳定、清楚且值得长期维护的 JSON 模块语义，而不是某段实现细节的便捷暴露；仅在确认需要长期对外承诺时再加入 Barrel 导出。

### 测试要求

- 若程序元素是函数，则只为该函数编写一个测试，如果该函数需要测试多个用例，应放在同一个测试中。
- 若程序元素是类，则至少要为该类的每一个方法编写一个测试，如果该方法需要测试多个用例，应放在同一个测试中。
- 若程序元素是类，除了为该类的每一个方法编写至少一个测试之外，还可以为该类编写任意多个测试，以覆盖该类的不同使用场景或边界情况。
- 若编写测试时需要用到辅助元素（Mock 或 Spy 等），可以在测试文件中直接定义这些辅助元素。若辅助元素较为简单，则可以直接放在每一个测试内部，优先保证每个测试的独立性，而不是追求极致 DRY；若辅助元素较为复杂或需要在多个测试中复用，则可以放在测试文件顶部，供该测试文件中的所有测试使用。
- 测试顺序应与源文件中被测试目标的原始顺序保持一致。
- 若该模块不需要测试，必须在说明文件中明确说明该模块不需要测试，并说明理由。一般来说，只有在该模块没有可执行的公共函数、只承载类型层表达，或其语义已被上层模块的测试完整覆盖且重复测试几乎不再带来额外价值时，才适合这样处理。
- 模块的单元测试文件目录是 `./tests/unit/json`，若模块包含子模块，则子模块的单元测试文件目录为 `./tests/unit/json/<sub-module-name>`。
- 测试应覆盖各公共能力各自的稳定语义。对于当前已有的 `repair`，重点覆盖可稳定修复的常见格式问题，以及超出修复边界时是否以明确失败结束，而不是返回含糊结果。
