我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

SEN(Simple Encoding Notation)格式详解:OjG 中省略引号与逗号的 JSON 超集

SEN(Simple Encoding Notation)格式详解:OjG 中省略引号与逗号的 JSON 超集 SENSimple Encoding Notation格式详解OjG 中省略引号与逗号的 JSON 超集【免费下载链接】inngestThe leading workflow orchestration platform. Run stateful step functions and AI workflows on serverless, servers, or the edge.项目地址: https://gitcode.com/GitHub_Trending/in/inngestSENSimple Encoding Notation是 Go 高性能 JSON 处理库 OjGOptimized JSON for Go内置的一种极简数据编码格式目标是用偷懒的方式写 JSON——省去多余的逗号和引号。本文以 OjG 的 SEN 规范文档为主体结合 gen/parser.go 等源码实现系统讲解 SEN 的语法规则、与 JSON 的兼容关系、解析器的底层实现以及它在当前仓库中的实际落地场景帮助你快速掌握这套可用于配置文件、CLI 参数、日志与调试输出的轻量格式。一、SEN 是什么从 JSON 出发的宽松版编码SEN 由 OjG 的作者 Peter Ohler 设计。OjG 的定位是为 Go 优化的大型数据集 JSON 解析库其 README 对 SEN 的概括非常精准Simple Encoding Notation, a lazy way to write JSON omitting commas and quotes.即一种省略逗号和引号来写 JSON 的偷懒方式。SEN 从 JSON 中汲取灵感但比 JSON 更不严格less strict。其核心设计哲学是任何合法的 SEN 解析器必须能解析 JSON——JSON 是 SEN 的严格子集SEN 是 JSON 的超集在 JSON 语法之外SEN 允许忽略逗号、允许把未加引号的 token 当作字符串读取、允许单引号字符串、允许//注释除此之外的所有方面SEN 与 json.org 对 JSON 的描述保持一致包括对象、数组、字符串、数字、布尔值、null 等类型的取值规则。由于 SEN 是 JSON 的超集它天然获得了两个实际好处内容可以无痛降级为标准 JSON且对人和程序都更友好——手写配置、调试输出、示例文档时不必纠结引号和逗号。二、SEN 的语法核心token 的 EBNF 定义SEN 最关键的语法创新在于无引号字符串token。一个 token 是由一组字符构成的序列其 EBNF 定义如下原文照录token tokenStart [{tokenContinue}] tokenStart letter | _ | ^ | . tokenContinue tokenStart | digit | - letter [A-Za-z_^~.] | U0080 - UFFFFFFFF digit [0-9]逐条解读规则含义tokenStarttoken 必须以字母、_、^或.开头tokenContinue后续字符可以是 tokenStart 允许的任何字符外加数字0-9和连字符-letter允许 ASCII 字母[A-Za-z]、下划线、^、~、.以及 U0080 至 UFFFFFFFF 的 Unicode 字符由此可推导出几个重要事实纯数字不会被误判为字符串token 不能以数字开头因此123、3.14、-5仍按 JSON 数值规则解析不会与字符串 token 冲突。Unicode 原生支持字符编码为 Unicode文件或流的编码必须是UTF-8在序列开头允许出现 UTF-8 BOM。连字符可在 token 内部出现例如some-token、v1.2-beta这类带-的标识符可以直接裸写无需引号。三、SEN 的宽松规则四条 JSON 之外的特权相比严格 JSONSEN 额外放开了以下四条规则1. 逗号可省略对象成员之间、数组元素之间的逗号不是必须的。解析器会依据上下文{/}、[/]、冒号、换行等自动推断边界。这是 SEN 最常用的偷懒点。2. 键与值可省略双引号符合 token 字符集的键和值都可以裸写。{ one: 1 }等价于{one: 1}数组元素同理[a b c]等价于[a, b, c]。3. 单引号字符串字符串除了用双引号abc分隔外也可以用单引号abc分隔。这对包含空格或特殊字符、无法构成合法 token 的字符串尤其有用例如{ name: hello world }。4.//行注释以//开头的 C 风格注释被允许且会被解析器忽略。这让 SEN 非常适合做配置文件格式——可以像写普通配置文件一样加注释。四、完整示例SEN 与 JSON 的等价对比sen.md 给出了一个合法的 SEN 文档示例{ one: 1 two: 2 array: [a b c] yes: true }这份 SEN 与下列 JSON 完全等价{ one: 1, two: 2, array: [a, b, c], yes: true }可以看到SEN 版本中对象键one、two、array、yes均未加引号成员之间没有逗号数组元素a、b、c裸写为字符串布尔值true仍按 JSON 布尔规则解析。再叠加单引号和注释能力一个更接近人类友好配置的 SEN 文档可以是// 应用配置逗号引号皆可省略 { name: api-server // 含空格用单引号 replicas: 3 features: [tracing metrics] enabled: true }五、源码级验证解析器如何实现这些宽松规则SEN 的语法规则在 OjG 的 gen/parser.go 中得到实现。gen.Parser是一个可复用的 JSON/SEN 解析器其Parse方法的核心流程可以从源码中得到印证BOM 与 UTF-8 处理sen.md 规定UTF-8 BOM 允许出现在序列开头对应实现位于 gen/parser.go当缓冲区前三个字节为0xEF 0xBB 0xBF时直接从第 4 个字节开始解析如果首字节是0xEF却跟的不是标准 BOM则返回expected BOM at 1:3错误// Skip BOM if present. if 3 len(buf) buf[0] 0xEF { if buf[1] 0xBB buf[2] 0xBF { err p.parseBuffer(buf[3:], true) } else { return nil, fmt.Errorf(expected BOM at 1:3) } } else { err p.parseBuffer(buf, true) }同样的 BOM 跳过逻辑也出现在ParseReader中gen/parser.go。状态机驱动的宽松解析parseBuffer是一个基于状态表p.mode指向的 mode 映射表的字节级状态机对每个字节根据当前状态决定是跳过分隔符、累积 token、读取引号字符串还是处理数值。从 gen/parser.go 可以看到skipChar跳过空白等字符、valQuote读取值引号内的字符串、numComma数字后紧跟逗号或成员边界等状态分支。正是这套状态机使解析器能够同时正确处理带逗号的严格 JSON和无逗号无引号的宽松 SEN而无需像许多解析器那样做两套解析逻辑。解析器复用与性能取向gen.Parser在设计上强调复用stack、tmp、starts、maps等内部缓冲在多次Parse调用间复用gen/parser.go从而减少内存分配。这与 OjG 整体的高性能定位一致——README 中的基准测试显示sen.Bytes输出 JSON 序列化可做到 0 次分配0 allocs/op远低于标准库json.Marshal。需要注意的是这些是仓库内自带的基准数据实际性能表现取决于具体使用场景。六、SEN 在当前仓库中的实际应用在 inngest 仓库中OjG 被作为第三方依赖 vendored 在 vendor/github.com/ohler55/ojg 下其中gen、jp等子包被表达式引擎使用。例如vendor/github.com/inngest/expr/engine_null.go 导入github.com/ohler55/ojg/jp用jp.ParseString(path)将变量名解析为 JSONPath 表达式再对map[string]any数据执行匹配类似的ojg/jp用法还出现在 engine_number.go、engine_stringbtree.go、engine_stringmap.go 等文件中用于事件/表达式数据的路径查找。从源码结构看当前仓库主要使用的是ojg的 JSONPathjp能力而 SEN 作为 OjG 体系中的编码格式其gen解析器与ojg顶层 API 共同构成了这套工具的完整能力面。若要在 Go 代码中使用 SEN可在项目中引入import ( github.com/ohler55/ojg/gen github.com/ohler55/ojg/sen )其中sen包提供 SEN 的序列化Bytes、String等gen.Parser负责兼容解析 JSON/SEN 输入。OjG 还提供oj.ParseString等高层入口可将 SEN/JSON 字符串解析为 Go 原生类型。七、使用建议与限制综合 sen.md 规范与源码实现给出如下使用建议把 SEN 当作 JSON 的输入方言而非替代品SEN 的价值在于让手写配置、调试输入、CLI 示例更省事对外接口、数据交换、存储格式仍应使用标准 JSON 以保证互操作性。遵守 token 边界规则裸写字符串时注意 token 不能以数字开头且内部不能出现空格空格是 token 分隔符含空格、#、:等字符的字符串请使用单引号或双引号包裹。文件编码固定 UTF-8文档明确要求 UTF-8BOM 允许但不强制解析器在遇到错误 BOM 时会报expected BOM错误。利用注释能力//注释使 SEN 非常适合做配置文件格式但要注意 JSON 严格模式解析器会拒绝注释——从 JSON 迁移到 SEN 配置时需要同时切换解析入口。性能取向需要高频、低分配解析时可复用gen.Parser实例Parse/ParseReader支持重复调用复用内部缓冲从 README 的基准看复用模式相比一次性解析有显著分配减少。八、参考与延伸阅读SEN 语法规范原文vendor/github.com/ohler55/ojg/sen.mdOjG 库总览与特性清单vendor/github.com/ohler55/ojg/README.mdgen 解析器实现BOM 处理、状态机解析vendor/github.com/ohler55/ojg/gen/parser.goOjG 设计文档含格式设计取舍vendor/github.com/ohler55/ojg/design.md当前仓库中对ojg/jp的实际使用示例vendor/github.com/inngest/expr/engine_null.go【免费下载链接】inngestThe leading workflow orchestration platform. Run stateful step functions and AI workflows on serverless, servers, or the edge.项目地址: https://gitcode.com/GitHub_Trending/in/inngest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表