精读《手写 JSON Parser》

本文围绕用 JavaScript 实现 JSON Parser 展开。先介绍解析 JSON 需理解语法概念,通过语法图说明 Object 等类型的产生式。接着阐述实现 Parser 的基本结构和解析过程,包括处理 Object、Array 等。还提及处理异常输入,如非法字符和非正常结尾。最后推荐语法解析入门系列文章。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 引言

JSON.parse 是浏览器内置的 API,但如果面试官让你实现一个怎么办?好在有人已经帮忙做了这件事,本周我们一起精读这篇 JSON Parser with Javascript 文章吧,再温习一遍大学时编译原理相关知识。

2 概述 & 精读

要解析 JSON 首先要理解语法概念,之前的 精读《手写 SQL 编译器 - 语法分析》 系列也有介绍过,不过本文介绍的更形象,看下面这个语法图:

这是关于 Object 类型的语法描述图,从左向右看,根据箭头指向只要能走出这个迷宫就属于正确语法。

比如第一行 { whitespace} 表示 { } 属于合法的 JSON 语法。

再比如观察向下的一条最长路线:{ whitespacestringwhitespace:value} 表示 { string : value } 属于合法的 JSON 语法。

你可能会问,双引号去哪儿了?这就是语法树最核心的概念了,这张图是关于 Object 类型的 产生式,同理还有 string、value 的产生式,产生式中可以嵌套其他产生式,甚至形成环路,以此拥有描述纷繁多变语法的能力。

最后我们再看一个环路,即 { whitespacestring,whitespacestring,},我们发现,只要不走回头路,这条路是可以一直 “绕圈” 下去的,因此 Object 类型拥有了任意数量子字段的能力,只是每形成一个子字段,必须经过 , 号分割。

实现 Parser

首先实现一个基本结构:

function fakeParseJSON(str) {
   
   
  let i = 0;
  // TODO
}

i 表示访问字符的下标,当 i 走到字符串结尾表示遍历结束。

然后是下一步,用几个函数描述解析语法的过程:

function fakeParseJSON(str) {
   
   
  let i = 0;
  function parseObject() {
   
   
    if (str[i] === '{') {
   
   
      i++;
      skipWhitespace();

      // if it is not '}',
      // we take the path of string -> whitespace -> ':' -> value -> ...
      while (str[i] !== '}') {
   
   
        const key = parseString();
        skipWhitespace();
        eatColon();
        const value = parseValue();
      }
    }
  }
}

其中 skipWhitespace 表示匹配并跳过空格,所谓匹配意味着匹配成功,此时 i 下标可以继续后移,否则匹配失败。下一步则判断如果 i 不是结束标志 },则按照 parseString 匹配字符串 → skipWhitespace 跳过空格 → eatColon 吃掉冒号 → parseValue 匹配值,这个链路循环。其中吃掉冒号表示 “匹配冒号但不会产生任何结果,所以就像吃掉了一样”,吃这个动作还可以用在其他场景,比如吃掉尾分号。

对于看到这儿的小伙伴,笔者要友情提示一下,原文的思路是一种定制语法解析思路,无论是 eatColon 还是 parseValue 都仅具备解析 JSON 的通用性,但不具备解析任意语法的通用性。如果你想做一个具备解析任何通用语法的解析器,读入的内容应该是语法描述,处理方式必须更加通用,如果感兴趣可以阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可口可乐Vip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值