一行 JSON.parse 背后藏着三步流水线:从零手搓 JSON 解析器
原创一行 JSON.parse 背后藏着三步流水线:从零手搓 JSON 解析器
一行调用背后:JSON 解析的三步流水线
第一次在代码里碰到 JSON 解析报错的时候,我盯着屏幕看了好一会儿。{"name": "juno", "tags": ["go", "json"]},这串东西在我眼里只是一行普通的文本,40 个字符,连标点都数得清楚。但对程序来说,它什么也没有,没有 name,没有 tags,没有嵌套对象,只有一串字符等着被拆开、被理解 来源:kothariji。这种"有"和"没有"之间的鸿沟,就是 JSON 解析器要跨过去的那道沟。
JavaScript 里解决这个问题只要一行,JSON.parse(text)。Python 用 json.loads,Go 用 json.Unmarshal,连 fetch 的 response.json() 背后也是同一个解析器在工作 来源:kothariji。调用入口都是一行代码,但文章作者 kothariji 在 Hacker News 上写了一段说明,'Your code calls JSON.parse all the time. This tutorial shows what happens inside it, and how to build a JSON parser yourself.' 来源:HN。这段话点破了一个我之前从来没琢磨过的问题,那一行代码里面到底在跑什么?
解析过程分三步走。第一步,解析器逐个字符地读文本,这时候 {、" 和空格对它来说没有区别,都只是字符。第二步,它把字符组装成有意义的 token,比如 "name"、冒号、方括号,空格在这一步消失。第三步,从 token 构建抽象语法树,也就是 AST,对象里包着数组,数组里包着 "go",嵌套关系全部展开 来源:kothariji。三步走下来,40 个字符变成了你程序能直接用的数据结构。
从 40 个字符到 AST:解析过程的技术细节
第一步比想象中朴素。解析器拿到那串文本后,从头到尾一个字符一个字符地扫。它不知道什么是对象,也不知道什么是字符串,在它眼里 { 和空格是同一种东西,就是字符流里的一个字节 来源:kothariji。这个阶段没有任何语义理解发生,纯粹是读取。
第二步开始有意思了。解析器把连续的字符按规则分组,形成 token。原文里有句话用得很精准,'because they mean nothing' 来源:kothariji。空格在这里消失,它们本来就不携带任何 JSON 语义。token 化之后,文本从一条 40 字符的线变成了若干个有名字的块,"name" 是一个字符串 token,冒号是一个分隔符 token,方括号是一个数组起始 token 来源:kothariji。
第三步,AST 构建阶段。tree 展示的是包含关系,object 内部有一个 array,array 内部有一个字符串 "go" 来源:kothariji。文章里做了一个交互式演示,点 Play 可以看到从原始文本到 token 再到 tree 的完整转换过程。它还给了几组交互实验,按 Tokens 按钮找空格去哪了,按 Tree 按钮看哪些字符没进树,选 "broken" 看看 token 正常但树出不来是什么情况 来源:kothariji。broken 那组我觉得特别有意思,token 阶段看起来都没问题,但组装树的时候规则校验失败,整棵树就出不来。这说明 token 化成功不等于解析成功,第三步的规则检查才是真正的关卡。
文章还明确了分工,第一步和第二步由一个叫 lexer 的组件负责,第三步由 parser 负责 来源:kothariji。lexer 管读字符和切 token,parser 管从 token 组装树。这个分工跟编译原理里的经典架构是一致的,不新鲜,但放在 JSON 解析这个日常场景里重新讲一遍,确实让我对底层有了更具体的感知。
跨语言解析器接口对比:JavaScript、Python 与 Go
三种主流语言的 JSON 解析入口都不一样,但长得都不难记。JavaScript 是 JSON.parse(text),示例代码里 console.log(user.tags[0]) 输出 "go" 来源:kothariji。Python 用 json.loads 处理字符串输入,Go 用 json.Unmarshal 做反序列化 来源:kothariji。三种语言的 API 设计思路略有差异,JavaScript 返回原生对象,Python 返回 dict 和 list,Go 要求你提前定义好 struct 再往里面填。但不管哪个语言,底层都绕不开同一套流程,逐字符读取、规则校验、结果构建。
fetch API 的 response.json() 也值得一提。很多人用 fetch 拉数据的时候直接调 response.json(),以为它返回的是一个已经解析好的 JSON 对象,但实际上它内部也调了一个 JSON 解析器 来源:kothariji。这条调用链上隐藏了一个完整的三步流水线,只不过浏览器帮你跑了而已。
文章用 Go 写代码示例,但作者特意说明不需要会 Go 也能看懂 来源:kothariji。我自己读完之后的感受是,JSON 解析器这件事的难度不在于算法复杂,而在于规则细致。要正确处理转义字符,要区分数字和字符串里的数字,要处理嵌套到任意深度的对象和数组。每一步看起来都是小事,但组合在一起就成了一个完整的工程问题。那行 JSON.parse 调用的背后,是一整套逐字符校验规则、逐段构建结果的流水线在跑。
原文:
Build your own JSON parser · 来源:Hacker News
参考来源:
作者:itfan123 值班编辑 · 发布于 2026年10月23日
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123





