ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

TOON 格式完全指南:从四形式语法到编码实现的深度剖析

TOON 格式完全指南:从四形式语法到编码实现的深度剖析 序列化AI 应用【免费下载链接】toon Token-Oriented Object Notation (TOON) – compact, human-readable serialization of JSON data for LLM prompts. TypeScript SDK, CLI, benchmarks.项目地址https://gitcode.com/gh_mirrors/toon/toon点击查看免费下载TOONToken-Oriented Object Notation是一种面向 LLM Prompt 场景、以最小化 Token 为目标的可读序列化格式本文基于仓库官方文档 docs/guide/format-overview.md 与 TypeScript SDK 源码系统讲解其四形式语法、数组表头、注释与引号规则并对照 packages/toon/src/encode/encoders.ts 等实现给出源码级依据帮助读者完整掌握 TOON 的读写、验证与自定义序列化能力。认识 TOON 的四种形式Form形式form是某个值的其中一种渲染方式。TOON 会根据数据的形状与所处位置自动选择形式——你永远不会手动指定。理解这四种形式是掌握 TOON 的第一步形式适用场景样子Inline内联原始类型数组tags[3]: admin,ops,devList列表既不满足内联也不满足表格形式的数组items[2]:后每元素一行-Tabular表格结构一致的对象数组items[2]{sku,qty}:后每个元素一行Keyed tabular键控表格值为同构对象的对象users[2:]{age,city}:后每个条目一行“形式”一词是刻意选择的这些是 TOON 内部的形状而不是 JSON 或 YAML 的同类格式。从源码看形式的选择逻辑集中在 packages/toon/src/encode/encoders.ts 的encodeJsonValue与encodeArrayLines中编码器先判断值是否为可编码原始类型再依次尝试isArrayOfPrimitives内联、isArrayOfArrays数组套数组、isArrayOfObjects表格或列表最终回退到混合数组的列表形式。整个判定过程全自动与文档所述“你永远不会选择形式”完全一致。数据模型与根形式TOON 与 JSON 采用相同的数据模型原始类型Primitives字符串、数字、布尔值、null对象Objects从字符串键到值的映射数组Arrays有序的值序列一份 TOON 文档可以呈现不同的根形式根对象最常见字段以深度 0 出现没有父级键根数组以深度 0 的[N]:或[N]{fields}:开头根原始类型单个原始值字符串、数字、布尔值或 null对象Objects简单对象原始值对象使用key: value语法每行一个字段缩进取代花括号冒号后跟一个空格id: 123 name: Ada active: true嵌套对象嵌套对象增加一个缩进层级默认 2 空格。当键以:结尾且同一行没有值时它开启一个嵌套对象下一缩进层级的所有行都属于该对象user: id: 123 name: Ada空对象根级别的空对象产生空文档没有行。嵌套空对象只有key:本身没有子行。键控表格对象Keyed Tabular Objects当一个对象至少有两条条目且这些条目的值都是结构一致的对象键相同、值为原始类型或一致嵌套对象时它就会折叠为键控表格形式共享字段结构在表头中出现一次每个条目成为一行并携带自己的键users[2:]{age,city}: alice: 30,Berlin bob: 25,Oslo紧跟长度后的冒号[2:]标记键控表头[N]声明条目数量。每个条目行是entrykey: cell,cell,…——条目键后跟该条目值按字段顺序排列的叶子值。当根对象本身符合条件时键被省略[2:]{age,city}: alice: 30,Berlin bob: 25,Oslo不合格的对象保持嵌套形式不变单条目对象、值混合多种形状的对象、值包含原始类型/数组/空对象的对象。实践中大多数配置类映射保持原样。对应实现见 packages/toon/src/encode/tabular.ts 的extractKeyedTabularFields要求至少两个非空对象条目且所有条目的值均为同构对象。数组ArraysTOON 自动检测数组结构并选择最高效的表示。数组始终在方括号中声明长度[N]。原始数组内联形式Inline Form原始类型数组字符串、数字、布尔值、null以内联形式渲染tags[3]: admin,ops,dev分隔符默认为逗号分隔各值。包含当前分隔符的字符串必须加引号。对象数组表格形式Tabular Form当数组中的所有对象共享同一组原始值键时TOON 使用表格形式items[2]{sku,qty,price}: A1,2,9.99 B2,1,14.5users[2]{id,name,role}: 1,Ada Lovelace,admin 2,Smith, Bob,user表头items[2]{sku,qty,price}:声明数组长度[2]表示 2 行字段名{sku,qty,price}定义列活动分隔符逗号默认每行按字段列表的顺序包含值。值为原始类型字符串、数字、布尔值、null用分隔符分隔。注意表格形式要求所有对象字段集合完全一致键相同键的顺序可不同、每个对象至少一个键且每列要么是原始值要么是一致嵌套对象见下文——数组中包含空{}元素或某一列混合值形状时会回退到列表形式。实现细节extractTabularFieldspackages/toon/src/encode/tabular.ts逐行校验每个对象是否拥有相同的键集合再通过classifyColumn对每列递归分类collectRowLeaves按字段顺序做深度优先遍历收集每行的叶子值。嵌套字段组Nested Field Groups值为一致子对象每个元素键相同递归为原始值或一致嵌套对象的列会折叠进表头作为嵌套字段组而行保持扁平orders[2]{id,customer{name,country},total}: 1,Ada,DK,99 2,Bob,UK,149表头customer{name,country}声明了一个嵌套对象列每行的单元格按字段列表的深度优先遍历填充因此Ada,DK填入第一个订单的customer.name与customer.country。嵌套深度无上限。在源码中表头的嵌套字段组由 packages/toon/src/encode/primitives.ts 的formatFieldSegment递归拼接解码端由 packages/toon/src/decode/parser.ts 的parseFieldEntries递归解析并生成FieldNode树。混合与非均匀数组列表形式List Form不满足表格要求的数组使用带连字符标记的列表形式items[3]: - 1 - a: 1 - text每个元素以-开头位于父数组表头更深一级的缩进位置。对象作为列表项数组元素为对象时它作为列表项出现items[2]: - id: 1 name: First - id: 2 name: Second extra: true当表格数组是列表项对象的第一个字段时表格表头出现在连字符行上行缩进两级更深其他字段缩进一级更深items[1]: - users[2]{id,name}: 1,Ada 2,Bob status: active当对象只有一个表格字段时模式相同items[1]: - users[2]{id,name}: 1,Ada 2,Bob这是首个字段为表格数组的列表项对象的规范编码。上述逻辑在 packages/toon/src/encode/encoders.ts 的encodeObjectAsListItemLines中实现首个字段若为可表格化的对象数组则表头落在-行深度 1表格行缩进到深度 2其余字段保持在深度 1。数组套数组List Form数组包含原始类型内层数组时pairs[2]: - [2]: 1,2 - [2]: 3,4每个内层数组在列表项行上获得自己的表头。当内层数组本身是对象数组或非均匀数组时同样的- [N]:表头出现在连字符行上嵌套项跟随更深一级缩进items[3]: - summary - id: 1 name: Ada - [2]: - id: 2 - status: draft空数组空数组在字段位置渲染为key: []在根位置渲染为[]items: []旧式items[0]:形式仍可解码用于向后兼容。编码端的对应分支见encodeArrayLines对value.length 0的处理packages/toon/src/encode/encoders.ts。数组表头Array Headers表头语法数组表头遵循以下模式key[Ndelimiter?]{fields}:其中N为非负整数长度delimiter可选显式声明活动分隔符缺省 → 逗号,\t制表符→ 制表分隔符|→ 竖线分隔符fields可选用于表格数组{field1,field2,field3}数组长度[N]帮助 LLM 校验结构。如果让模型生成 TOON 输出显式长度可用来检测截断或畸形数据。表头的解析实现在 packages/toon/src/decode/parser.ts 的parseArrayHeaderLine与parseBracketSegment中长度必须匹配^(?:0|[1-9]\d*)$不允许前导零分隔符后缀\t或|与键控冒号:从括号内容尾部依次剥离识别。分隔符选项TOON 支持三种分隔符逗号默认、制表符、竖线。分隔符作用域为声明它的数组表头items[2]{sku,name,qty,price}: A1,Widget,2,9.99 B2,Gadget,1,14.5items[2 ]{sku name qty price}: A1 Widget 2 9.99 B2 Gadget 1 14.5items[2|]{sku|name|qty|price}: A1|Widget|2|9.99 B2|Gadget|1|14.5制表与竖线分隔符在表头方括号与字段花括号中显式编码。在数组作用域内只有活动分隔符会触发引号包裹其余分隔符是字面数据。对象字段值key: value遵循文档分隔符不受周围数组活动分隔符的影响。提示制表分隔符通常比逗号带来更好的分词效率尤其是引号字符串较少的数据。使用encode(data, { delimiter: \t })可以进一步节省 Token。分隔符校验在 packages/toon/src/shared/validation.ts 的assertValidDelimiter中完成仅接受逗号,、制表\t、竖线|三者之一库与 CLI 共用同一套校验报错信息一致。注释Comments解码器在任何其他处理之前先对每一行做词法预处理第一个非空格字符为#的行会被剥离# Server configuration host: example.com port: 8080注释仅支持整行——行内其他位置的#是普通内容——且只在解码端生效编码器从不输出注释以#开头的字符串值始终被加引号因此编码器输出永远不会出现会被读成注释的行。表格行或条目行之间的注释不会终止它们。源码印证isSafeUnquotedpackages/toon/src/shared/validation.ts将startsWith(#)列为必须引号的场景之一字符串字面量中的#由编码侧自动加引号保护。引号与类型Quoting and Types何时字符串需要引号TOON 只在必要时给字符串加引号以最大化 Token 效率。字符串必须加引号的情况空字符串有前导或尾随空白等于true、false或null区分大小写看起来像数字例如42、-3.14、1e-6、05、1包含特殊字符冒号:、引号、反斜杠\、方括号、花括号或任何 U0000–U001F 控制字符包含相关分隔符数组作用域内为活动分隔符其他位置为文档分隔符等于-或以-后跟任意字符开头等于#或以#开头该行会被读成注释否则字符串可以不引号。Unicode、emoji 以及含内部非首尾空格的字符串不加引号也是安全的message: Hello 世界 note: This has inner spaces这些规则在 packages/toon/src/shared/validation.ts 的isSafeUnquoted中逐一实现仅空格与制表符强制引号与宿主trim()剥离全部 Unicode 空白的行为不同数字形状判定使用NUMERIC_LIKE_PATTERN正则。转义序列在带引号的字符串和键中只有六种转义序列有效字符转义反斜杠\\\双引号\换行U000A\n回车U000D\r制表符U0009\t任何其他 U0000–U001F 控制字符\uXXXX其他转义如\x、\0、\b一律拒绝独立的代理项\uXXXX值UD800–UDFFF同样拒绝。实现位于 packages/toon/src/shared/string-utils.tsescapeString按上述映射输出unescapeString对未知转义与孤立代理项抛出SyntaxError。类型转换数字在 §2 carve-out 范围内以规范十进制形式输出范围外允许指数记数法。非 JSON 类型NaN、Infinity、BigInt、Date、Set、Map、undefined等在编码前被规范化——完整映射见 API Reference – Type Normalization。解码器在输入时同时接受十进制与指数形式如42、-3.14、1e-6并把含禁止前导零的 Token如05当作字符串而非数字。这一点在 packages/toon/src/shared/literal-utils.ts 的NUMERIC_LITERAL_PATTERN中得到印证数字字面量拒绝前导零0本身及0.5这类小数除外而编码侧的isNumericLike用于“长得像数字”的判定保证05被引号包裹、解码时作为字符串原样返回。使用 toJSON 自定义序列化带有toJSON()方法的对象在编码前会调用该方法并规范化其结果行为类似JSON.stringifyconst obj { data: example, toJSON() { return { info: this.data } } } encode(obj) // info: exampletoJSON()方法优先于内置规范化Date、Array、Set、Map其结果会被递归规范化原型链上存在toJSON的对象也会被调用实现见 packages/toon/src/encode/normalize.ts 的normalizeValue检测到toJSON后先调用再递归并避免toJSON返回自身时的无限递归。编码器实现速览文档中的全部语法行为在 packages/toon/src/encode/encoders.ts 中有清晰对应encodeJsonValue负责根值分发encodeArrayLines按“空数组 → 原始数组内联 → 数组套数组 → 对象数组表格/列表 → 混合列表”的顺序选择形式encodeKeyedObjectLines与encodeArrayOfObjectsAsTabularLines分别输出键控表格与表格形式formatHeaderpackages/toon/src/encode/primitives.ts统一拼装key[Ndelim?{fields}]:表头。编码入口encode/encodeLines与解码入口decode/decodeFromLines/decodeStream见 packages/toon/src/index.ts其中decode默认开启strict: true模式用于强校验数组长度与表格行数可通过{ strict: false }关闭。实战读写与验证完整语法之外可以立即用仓库 CLI 或 SDK 验证本文示例。编码侧使用encode/encodeLines含delimiter、indentSize、replacer选项解码侧使用decode/decodeFromLines/decodeStream含strict选项详见 API ReferenceCLI 支持 JSON↔TOON 转换、--statsToken 统计与 stdin/stdout 管道见 CLI 文档。入门安装与首个示例见 Getting Started完整规范可查阅仓库根目录的 SPEC.md。进一步阅读Getting Started —— 安装与快速上手Syntax Cheatsheet —— 语法速查表API Reference —— TypeScript/JavaScript 编码解码 APIBenchmarks —— 检索准确率与 Token 效率对比数据LLM Prompts —— 面向模型的 Prompt 策略与校验技巧SPEC.md —— 面向实现者的规范性规则赞分享序列化AI 应用【免费下载链接】toon Token-Oriented Object Notation (TOON) – compact, human-readable serialization of JSON data for LLM prompts. TypeScript SDK, CLI, benchmarks.项目地址https://gitcode.com/gh_mirrors/toon/toon点击查看免费下载相关推荐Hurl 语法完全指南深入解析 hurl 文件格式的形式文法GrammarHurl 语法完全指南深入解析 hurl 文件格式的形式文法Grammar 本篇技术指南围绕 Hurl 项目官方语法文档 docs/grammar.md接口测试测试开发工具TOON 格式规范Spec深度导读语法定义、一致性检查清单与实现者指南TOON 格式规范Spec深度导读语法定义、一致性检查清单与实现者指南 TOONToken Oriented Object Notation是面向 L序列化AI 应用BlenderToolbox动画制作教程如何创建高质量3D科学可视化动画BlenderToolbox动画制作教程如何创建高质量3D科学可视化动画 BlenderToolbox是一套简单实用的Blender脚本工具专为创建高质量3上一篇开源项目 Wind-JS 使用教程下一篇Netcode 项目使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表