JSON.parse 是我们在前端开发中经常会用到API,如果我们要自己实现一个JSON.parse,我们应该怎么实现呢?今天我们就试着手写一个JSON Parser,了解下其内部实现原理。
JSON语法
JSON 是一种语法,用来序列化对象、数组、数值、字符串、布尔值和 null 。语法规则如下:
- 数据使用名/值对表示。
- 使用大括号({})保存对象,每个名称后面跟着一个 '
冒号),名/值对使用 ,(逗号)分割。
- 使用方括号([])保存数组,数组值使用 ,(逗号)分割。
- JSON值可以是:数字(整数或浮点数)/字符串(在双引号中)/逻辑值(true 或 false)/数组(在方括号中)/对象(在花括号中)/null
实现Parser
Parser 一般会经过下面几个过程,分为词法分析 、语法分析、转换、代码生成过程。
词法分析
通过对 JSON 语法的了解,我们可以看到 JSON 中会有一下类型及其特征如下表:
类型基本特征Object"{" ":" "," "}"Array"[" "," "]"String'"'Number"0" "1" "2" "3" "4" "5" "6" "7" "8" "9"Boolean"true" "false"Null"null"所以根据这些特征,对 JSON 字符串进行遍历操作并与上述特征进行对比可以得到相应的 token。词法分析实现代码如下:
[code]// 词法分析const TokenTypes = { OPEN_OBJECT: '{', CLOSE_OBJECT: '}', OPEN_ARRAY: '[', CLOSE_ARRAY: ']', STRING: 'string', NUMBER: 'number', TRUE: 'true', FALSE: 'false', NULL: 'null', COLON: ':', COMMA: ',',}class Lexer { constructor(json) { this._json = json this._index = 0 this._tokenList = [] } createToken(type, value) { return { type, value: value || type } } getToken() { while (this._index < this._json.length) { const token = this.bigbang() this._tokenList.push(token) } return this._tokenList } bigbang() { const key = this._json[this._index] switch (key) { case ' ': this._index++ return this.bigbang() case '{': this._index++ return this.createToken(TokenTypes.OPEN_OBJECT) case '}': this._index++ return this.createToken(TokenTypes.CLOSE_OBJECT) case '[': this._index++ return this.createToken(TokenTypes.OPEN_ARRAY) case ']': this._index++ return this.createToken(TokenTypes.CLOSE_ARRAY) case ':': this._index++ return this.createToken(TokenTypes.COLON) case ',': this._index++ return this.createToken(TokenTypes.COMMA) case '"': return this.parseString() } // number if (this.isNumber(key)) { return this.parseNumber() } // true false null const result = this.parseKeyword(key) if (result.isKeyword) { return this.createToken(TokenTypes[result.keyword]) } } isNumber(key) { return key >= '0' && key |