一个JSON解析器
来源
《JavaScript语言精粹(修订版)》
代码
<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
</head> <body>
<script>
var json_parse = function () {
var
at,
ch,
escapee = {
'"': '"',
'\\': '\\',
'/': '/',
b: 'b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
},
text,
// 抛出异常
error = function (m) {
throw {
name: 'SyntaxError',
message: m,
at: at,
text: text
}
},
// 获取下一个字符
next = function (c) {
if (c && c !== ch) {
error(`Expected ${c} instead of ${ch}`);
}
ch = text.charAt(at);
at += 1;
return ch;
},
// 解析一个数字值
number = function () {
var number, string = '';
// 负号
if (ch === '-') {
string = '-',
next('-')
}
// 整数
while (ch >= '0' && ch <= '9') {
string += ch;
next();
}
// 小数
if (ch === '.') {
string += '.';
while (next() && ch >= '0' && ch <= '9') {
string += ch;
}
}
// 指数
if (ch === 'e' || ch === 'E') {
string += ch;
next();
if (ch === '-' || ch === '+') {
string += ch;
next();
}
while (ch >= '0' && ch <= '9') {
string += ch;
next();
}
}
number = +string;
if (isNaN(number)) {
error('Bad number')
} else {
return number;
}
},
// 解析一个字符串值
string = function () {
var hex,
i,
string = '',
uffff;
// 字符串必须以双引号开始
if (ch === '"') {
while (next()) {
if (ch === '"') {
next();
return string;
} else if (ch === '\\') {
next();
// unicode码
if (ch === 'u') {
uffff = 0;
for (i = 0; i < 4; i++) {
hex = parseInt(next(), 16);
if (!isFinite(hex)) {
break;
}
ufff = ufff * 16 + hex;
}
string += String.fromCharCode(ufff)
}
else if (typeof escapee[ch] === 'string') { // 转义字符
string += escapee[ch]
} else {
break;
}
} else {
string += ch;
}
}
}
error('Bac string');
},
// 跳过空白
white = function () {
while (ch && ch <= ' ') {
next();
}
},
// 解析 true、false、null
word = function () {
switch (ch) {
case 't':
next('t');
next('r');
next('u');
next('e');
return true;
case 'f':
next('f');
next('a');
next('l');
next('s');
next('e');
return true;
case 'n':
next('n');
next('u');
next('l');
next('l');
return true;
}
error(`Unexpected ${ch}`)
},
// 解析一个数组值
array = function () {
var array = [];
if (ch === '[') {
next('[');
white();
if (ch === ']') {
next(']');
return array;
}
while (ch) {
array.push(value());
white();
if (ch === ']') {
next(']');
return array;
}
next(',');
white();
}
}
error('Bad array');
},
// 解析一个对象值
object = function () {
var key, object = {};
if (ch === '{') {
next('{');
white();
if (ch === '}') {
next('}');
return object;
}
while (ch) {
key = string();
white();
next(':');
object[key] = value();
white();
if (ch === '}') {
next('}');
return object;
}
next(',');
white();
}
}
error('Bad object');
},
// 解析一个JSON值。它可以是对象、数组、字符串、数字、一个词。
value = function () {
white();
switch (ch) {
case '{':
return object();
case '[':
return array();
case '"':
return string();
case '-':
return number;
default:
return ch >= '0' && ch <= '9' ? number() : word();
}
};
// 返回json_parse函数
return function (source, reviver) {
var result;
text = source;
at = 0;
ch = ' ';
result = value();
white();
if (ch) { // 多余的非空白字符
error('Syntax error');
}
return typeof reviver === 'function' ? function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === 'object') {
// 递归处理对象的属性
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k]
}
}
}
}
// 处理对象
return reviver.call(holder, key, value);
}({ '': result }, '') : result;
}
}();
// \n是一个字符,\\n是两个字符
const str = '{"name":"饮料","price":2.5,"cool":true,"description":["雪碧","可乐"],"escapseSlash":"\\/","escapeN":"\\n"}';
console.log(json_parse(str, (key, val) => val))
</script>
</body> </html>
运行结果

一个JSON解析器的更多相关文章
- 一起写一个JSON解析器
[本篇博文会介绍JSON解析的原理与实现,并一步一步写出来一个简单但实用的JSON解析器,项目地址:SimpleJSON.希望通过这篇博文,能让我们以后与JSON打交道时更加得心应手.由于个人水平有限 ...
- 如何编写一个JSON解析器
编写一个JSON解析器实际上就是一个函数,它的输入是一个表示JSON的字符串,输出是结构化的对应到语言本身的数据结构. 和XML相比,JSON本身结构非常简单,并且仅有几种数据类型,以Java为例,对 ...
- 几百行代码实现一个 JSON 解析器
前言 之前在写 gscript时我就在想有没有利用编译原理实现一个更实际工具?毕竟真写一个语言的难度不低,并且也很难真的应用起来. 一次无意间看到有人提起 JSON 解析器,这类工具充斥着我们的日常开 ...
- 自己动手实现一个简单的JSON解析器
1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等.在 ...
- 用c#自己实现一个简单的JSON解析器
一.JSON格式介绍 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着很多优点.例如易读性更好,占用空间更 ...
- 面试题|手写JSON解析器
这周的 Cassidoo 的每周简讯有这么一个面试题:: 写一个函数,这个函数接收一个正确的 JSON 字符串并将其转化为一个对象(或字典,映射等,这取决于你选择的语言).示例输入: fakePars ...
- 手写Json解析器学习心得
一. 介绍 一周前,老同学阿立给我转了一篇知乎回答,答主说检验一门语言是否掌握的标准是实现一个Json解析器,网易游戏过去的Python入门培训作业之一就是五天时间实现一个Json解析器. 知乎回答- ...
- 一个简单的json解析器
实现一个简单地json解析器. 两部分组成,词法分析.语法分析 词法分析 package com.mahuan.json; import java.util.LinkedList; import ja ...
- 这个东西,写C++插件的可以用到。 RapidJSON —— C++ 快速 JSON 解析器和生成器
点这里 原文: RapidJSON —— C++ 快速 JSON 解析器和生成器 时间 2015-04-05 07:33:33 开源中国新闻原文 http://www.oschina.net/p/ ...
随机推荐
- tomcat+redis接上篇
数据库允许远程连接 把数据库中的mysql数据库中的user表里的host项为localhost的改为 % update user set host = '%' where user = 'root' ...
- 017-zabbix_proxy分布式监控部署
一.proxy分布式监控介绍 来源于zabbix官网: https://www.zabbix.com/documentation/3.4/zh/manual/distributed_monitorin ...
- (转) Weblogic 12c 集群部署和session复制
1.启动服务 首先在weblogic12c控制台,启动受托管服务server1.server2.server3. 2.将要部署的应用打包成war文件. 我用的是MyEclipse做的开发,可以用其自带 ...
- [POJ1664]放苹果(动态规划)
[POJ1664]放苹果 Description 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第 ...
- 别再误解MySQL和「幻读」了
The so-called phantom problem occurs within a transaction when the same query produces different set ...
- javascript(腾讯)
var a={key:"1",value:2}; war b=a; b.value+=a.key, 打印b.value是多少,a.value呢? 答案:都是21.因为javascr ...
- Mybatis-Plus和Mybatis的区别
1.List item 区别一如果Mybatis Plus是扳手,那Mybatis Generator就是生产扳手的工厂.通俗来讲——MyBatis:一种操作数据库的框架,提供一种Mapper类,支持 ...
- sql len函数 CASE WHEN
SELECT LEN('SQL Server LEN') length, LEN('SQL Server LEN ') length_with_trailing_blanks; SELECT (CAS ...
- webpack--第三方loader
1.配置处理css样式表的第三方loader webpack默认只能打包处理js类型的文件,无法处理非js类型的文件:要想处理*.css文件,需要手动安装一下合适的第三方loader加载器: npm ...
- Linux培训教程 浅谈:PHP在linux上执行外部命令(整理)
一.PHP中调用外部命令介绍 二.关于安全问题 三.关于超时问题 四.关于PHP运行linux环境中命令出现的问题 一.PHP中调用外部命令介绍 在PHP中调用外部命令,可以用,1>调用专门函数 ...