JSON 家族识别指南:Understand-Anything 如何将 JSON/JSONC/JSON Schema 解析为知识图谱节点
【免费下载链接】Understand-AnythingGraphs that teach > graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.项目地址: https://gitcode.com/GitHub_Trending/un/Understand-Anything
本文聚焦 Understand-Anything 项目中understandskill 的 JSON 语言分析片段(languages/json.md),剖析它如何指导代码分析 Agent 在生成项目知识图谱时正确理解package.json、tsconfig.json、*.schema.json等非代码文件的核心语法、常见模式与语义关系,并配套讲解其底层语言配置、扫描分类与 JSON/JSONC 解析器的实现。读完本文,你将掌握该图谱工具处理"配置型 JSON 生态"的完整链路,并能据此判断与分析 JSON 相关文件在项目架构中的角色。
语言片段:注入架构分析的一线语义知识
在 Understand-Anything 的七阶段分析流程中,语言片段在Phase 4(ARCHITECTURE)被投入使用。根据 SKILL.md 中的说明,架构分析子代理(architecture-analyzer)在下发前,会针对 Phase 1 检测到的每一种语言,读取 languages/ 目录下对应的<language-id>.md文件,将其内容附加到提示模板的## Language Context之后——JSON 的对应文件正是本篇文章的主题文档 json.md。
值得强调的是,这些"非代码语言片段"与代码语言片段同等重要。设计意图在 SKILL.md 中写得很明确:"Include non-code language snippets — they provide edge patterns and summary styles for non-code files."(请包含非代码语言片段——它们为非代码文件提供边缘模式和摘要风格。)也就是说,当分析一个以package.json、tsconfig.json或 JSON Schema 为主的项目时,Phase 4 的层分配与关系判定质量,直接依赖这段 JSON 语义知识。
片段本身通常不长(约 40 行),但信息密度高:它浓缩了 JSON 家族的核心概念(Key Concepts)、常见文件模式(Notable File Patterns)、边缘模式(Edge Patterns,即该文件与其他文件如何建立关系边)以及摘要风格(Summary Style)。下面逐节拆解,并对照仓库源码还原其背后的真实实现。
核心概念:JSON 家族与它的"变体光谱"
文档首先划定 JSON 语言家族的分析边界,共七条关键概念,可分为两个层次:
标准 JSON 的硬性语法规则:
- 严格语法(Strict Syntax):不允许尾随逗号、不允许注释(这是与 JSONC/JSON5 的关键分界)、字符串只能使用双引号;
- 数据类型(Data Types):对象、数组、字符串、数字、布尔值与
null——没有undefined与日期类型(这一点使 JSON 无法直接表达 JS 的undefined,日期通常序列化为 ISO 字符串); - 嵌套结构(Nested Structure):支持任意深度的递归嵌套,这是它能承载层级化配置与数据结构的根本原因。
围绕标准 JSON 形成的扩展/变体:
- Schema 校验(Schema Validation):通过 JSON Schema 与
$schema关键字描述并校验结构与类型; - JSONC:带注释的 JSON 变体,被 VS Code、
tsconfig.json及大量前端工具链采用; - JSON5:进一步放宽语法的扩展——允许注释、尾随逗号、非引号键名等;
- JSON Lines(
.jsonl):每行一个 JSON 对象,面向流式数据处理。
仓库中的语言配置忠实体现了这一边界。在 json-config.ts 中,JSON 语言的注册配置为:
export const jsonConfigConfig = { id: "json", displayName: "JSON", extensions: [".json", ".jsonc"], // 同时接管 .json 与 .jsonc concepts: ["objects", "arrays", "nesting", "schema references", "comments (JSONC)"], filePatterns: { entryPoints: ["package.json"], barrels: [], tests: [], config: ["tsconfig.json", "package.json", ".eslintrc.json"], }, } satisfies LanguageConfig;concepts字段与语言片段中的 Key Concepts 高度一致(objects、arrays、nesting、schema references、comments (JSONC));filePatterns.config则把tsconfig.json、package.json、.eslintrc.json列为该语言"配置文件形态"的代表模式——这正是片段中 Notable File Patterns 前半部分的来源。你可以在 index.ts 看到它与其他二十多种语言配置一起被导出并合入builtinLanguageConfigs。
从扩展名到节点类型:JSON 文件如何在扫描中被归类
在 Phase 1(SCAN)中,扫描脚本 scan-project.mjs 负责为每个文件推断语言与类别,JSON 家族在此处的规则清晰可见:
- 语言映射:
.json→json,.jsonc→jsonc(源码中同时存在.yaml/.yml/.toml/.xml等非代码语言映射); - 类别映射:
.json与.jsonc均归类为config(配置类),与.yaml、.toml、.env等同属一类。
随后,file-analyzer.md 中的"fileCategory → 节点类型"映射将config类别映射为知识图谱中的config节点,ID 形如config:<relative-path>,例如config:package.json、config:tsconfig.json。本仓库自身就是一个绝佳实例:根目录的 package.json、tsconfig.json 以及 pnpm-workspace.yaml 等都属于此类节点。
一个值得注意的边界:JSON Schema(*.schema.json)并没有独立扩展名。在 json-schema.ts 中,其配置的extensions为空数组,并留有一段明确的 TODO 注释说明设计取舍:
JSON Schema files have no unique extension —
*.schema.jsonfiles will matchjsonConfigConfigby the.jsonextension. Detection requires content-based heuristics (e.g., checking for"$schema"or"type"keys at the root level).
也就是说,*.schema.json目前按.json扩展名落入json语言配置,其"Schema 身份"依赖内容启发式判断(如根级$schema或type键)来做进一步区分——这一点在阅读图谱结果时值得留意:Schema 类文件在节点类型上可能是schema:<path>也可能是config:<path>,取决于内容层面如何被判定。
常见文件模式:图谱中最常出现的 JSON 文件
文档给出七类高频 JSON 文件模式,它们是分析任何真实项目时几乎必然遇到的:
| 文件模式 | 典型作用域 | 分析要点 |
|---|---|---|
package.json | Node.js 项目 | 依赖(dependencies)、脚本(scripts)与项目元数据 |
tsconfig.json | TypeScript | 编译器配置(注意:实际上是 JSONC,允许注释与尾随逗号) |
.eslintrc.json | ESLint | 静态检查规则与配置 |
*.schema.json | 数据校验 | JSON Schema 定义 |
composer.json | PHP Composer | PHP 包与依赖清单 |
appsettings.json | .NET | 应用运行时配置 |
manifest.json | 浏览器扩展 / PWA | Web 应用清单 |
从源码结构看,本仓库对这些模式的处理呈"多文件覆盖"形态:JSONConfigParser的注释明确提到它处理package.json、tsconfig.json、wrangler.jsonc、JSON Schema 与 OpenAPI 规格文件(见下节);dashboard 子包(understand-anything-plugin/packages/dashboard)中可见真实的package.json、tsconfig*.json、vite.config.ts;而 knowledge-graph.json 本身即是图谱输出物——JSON 既是"被分析对象",也是"分析产物"。
底层解析器:JSONConfigParser 如何"读懂" JSON/JSONC
语言片段只负责告诉 LLM"该关注什么",而真正确定性提取结构的,是 json-parser.ts 中的JSONConfigParser。它注册的语言集合为["json", "jsonc", "json-schema", "openapi"],这意味着 JSON 家族的多种风味都会走同一解析路径,避免落入"no parser matched"分支而丢失结构提取。
JSONC 语法剥离:stripJsoncSyntax
由于tsconfig.json等文件是 JSONC 而非严格 JSON,直接JSON.parse会失败。解析器先调用stripJsoncSyntax做三件事的预处理:
- 字符串字面量原样保留——遇到双引号则逐字符复制并正确处理
\转义序列,确保字符串内部的//或/*不会被误当注释删除; - 行注释剥离(
// ...)与块注释剥离(/* ... */); - 尾随逗号清洗——通过正则
/,(\s*[}\]])/g删除}或]之前的逗号。
纯 JSON 内容不含这三类语法,因此会原样通过,几乎无性能损失。
顶层键提取为 sections
extractSections解析成功后,只遍历根对象(不递归深入嵌套子结构),把每个顶层键作为一条sections记录返回,并尽力定位其在源文件中的真实行号(用JSON.stringify(key)做转义后再去原文逐行查找,保证tsconfig.json中带注释的行号与用户所见一致),最后把相邻 section 的行区间补全。于是像package.json的name、scripts、dependencies、devDependencies这样的顶层键,会成为图谱中描述"该配置文件管什么"的原始结构证据。
$ref外部引用提取
extractReferences用正则/"\$ref"\s*:\s*"([^"]+)"/g抓取 JSON Schema / OpenAPI 中的$ref,跳过以#开头的内部引用,把指向外部文件的引用解析为referenceType: "schema"的引用记录(含源文件、目标与行号)——这为后续建立跨文件的语义边提供了确定性锚点。
值得注意的是,该解析器处理失败并不会让分析中断,而是console.warn输出一行 "Failed to parse JSON" 后返回空 sections,体现"可降级、保留部分结果"的整体容错哲学。
边缘模式:JSON 文件如何长出"关系边"
语言片段 Edge Patterns 部分用动词明确了每类 JSON 文件的语义角色:
package.jsonconfigures(配置)构建工具链,定义项目依赖;tsconfig.jsonconfigures所有.ts文件的 TypeScript 编译;- JSON Schema 文件defines_schema(定义结构),服务于 API 请求/响应的校验;
- 运行时配置 JSONconfigures应用的运行时行为。
这些动词与图谱边类型一一对应。在 file-analyzer.md 的非代码边规则表中,configures边的方向为 forward、权重 0.6,用于"配置文件影响某个代码文件或模块"(例:tsconfig.json配置 TypeScript 编译、.env配置运行时);defines_schema权重 0.8,用于"Schema 文件定义代码所用结构"。文件分析 Agent 被明确要求:tsconfig.json应对所有.ts文件建configures边,package.json应对构建入口建configures边;Schema 文件则应对实现该数据结构的处理代码建defines_schema边。
在知识图谱 Schema 的边类型总表中(见 SKILL.md Reference 部分),这两个边分属Dependencies(configures)与Schema/Data(defines_schema)两个类别。加上从图谱输出的类型约定可推断:schema:<path>节点专用于 GraphQL/Protobuf/Prisma 等 Schema 定义,而 JSON Schema(*.schema.json)在实际运行中会经由 JSON 解析器路径与config/schema节点身份之间的内容判定——这类"推断性结论"需要在阅读具体项目图谱时结合节点 ID 前缀确认。
摘要风格:让每个 JSON 节点"一句话讲清自己"
语言片段以三条示例句给出 JSON 文件节点摘要的写作范式:
"Node.js project manifest defining N dependencies, build scripts, and project metadata." "TypeScript compiler configuration enabling strict mode with path aliases for monorepo packages." "JSON Schema defining the request/response structure for the user API endpoint."
这与 file-analyzer.md 对配置类文件的摘要要求完全同构:"Describe what the config controls"(描述这份配置控制了什么),并给出反例与正例——反例 "The utils file contains utility functions",正例如 "TypeScript compiler configuration enabling strict mode with path aliases for the monorepo"。
把片段规则与 Agent 规范对照,可以提炼出撰写 JSON 节点摘要的四条实用准则:
- 动词导向:使用
defining、configuring、enabling等说明"作用",而非静态描述"包含"; - 点出被作用对象:manifest 之于项目、tsconfig 之于
.ts文件、Schema 之于 API 接口; - 携带关键决策:strict mode、path aliases、依赖数量 N 等具体事实比形容词更有检索价值;
- 配套 tags 词汇:非代码文件常用
configuration、build-system、schema-definition、api-schema等标签,与摘要互相印证。
对本仓库图谱的直接观察
将上述规则应用回本仓库,可以立刻看到 JSON 节点在真实项目中的分布形态:
- 仓库根与各包(core、dashboard、homepage)的 package.json 被归为
config类节点,承担 monorepo(pnpm workspace)依赖管理职责,应对pnpm-workspace.yaml及构建脚本建立关系; - 各层的 tsconfig.json /
tsconfig.app.json以 JSONC 形态存在,应与其覆盖的.ts/.tsx源码建立configures边; - dashboard 的 knowledge-graph.json 则是"图谱即数据"的产物文件,若要二次分析可复用同一套 JSON 解析与 Schema 识别逻辑。
小结
以 json.md 为代表的语言片段,是 Understand-Anything 将"非代码配置资产"纳入知识图谱的关键语义层:它在 Phase 4 把 JSON 家族的语法边界、高频文件模式、关系动词与摘要范式注入架构分析子代理;而json-config.ts/json-schema.ts的语言配置、scan-project.mjs 的扩展名分类、以及 json-parser.ts 的 JSONC 剥离与$ref提取,共同构成该语义层下方的确定性引擎。理解这一"语言片段(语义)+ 解析器(结构)"的双层设计,不仅能帮你读懂图谱中 JSON 节点的由来,也为扩展或复用它分析自身项目中的 JSON 资产提供了清晰的参考路径。
【免费下载链接】Understand-AnythingGraphs that teach > graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.项目地址: https://gitcode.com/GitHub_Trending/un/Understand-Anything
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考