来源

《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解析器的更多相关文章

  1. 一起写一个JSON解析器

    [本篇博文会介绍JSON解析的原理与实现,并一步一步写出来一个简单但实用的JSON解析器,项目地址:SimpleJSON.希望通过这篇博文,能让我们以后与JSON打交道时更加得心应手.由于个人水平有限 ...

  2. 如何编写一个JSON解析器

    编写一个JSON解析器实际上就是一个函数,它的输入是一个表示JSON的字符串,输出是结构化的对应到语言本身的数据结构. 和XML相比,JSON本身结构非常简单,并且仅有几种数据类型,以Java为例,对 ...

  3. 几百行代码实现一个 JSON 解析器

    前言 之前在写 gscript时我就在想有没有利用编译原理实现一个更实际工具?毕竟真写一个语言的难度不低,并且也很难真的应用起来. 一次无意间看到有人提起 JSON 解析器,这类工具充斥着我们的日常开 ...

  4. 自己动手实现一个简单的JSON解析器

    1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等.在 ...

  5. 用c#自己实现一个简单的JSON解析器

    一.JSON格式介绍 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着很多优点.例如易读性更好,占用空间更 ...

  6. 面试题|手写JSON解析器

    这周的 Cassidoo 的每周简讯有这么一个面试题:: 写一个函数,这个函数接收一个正确的 JSON 字符串并将其转化为一个对象(或字典,映射等,这取决于你选择的语言).示例输入: fakePars ...

  7. 手写Json解析器学习心得

    一. 介绍 一周前,老同学阿立给我转了一篇知乎回答,答主说检验一门语言是否掌握的标准是实现一个Json解析器,网易游戏过去的Python入门培训作业之一就是五天时间实现一个Json解析器. 知乎回答- ...

  8. 一个简单的json解析器

    实现一个简单地json解析器. 两部分组成,词法分析.语法分析 词法分析 package com.mahuan.json; import java.util.LinkedList; import ja ...

  9. 这个东西,写C++插件的可以用到。 RapidJSON —— C++ 快速 JSON 解析器和生成器

    点这里 原文: RapidJSON —— C++ 快速 JSON 解析器和生成器 时间 2015-04-05 07:33:33  开源中国新闻原文  http://www.oschina.net/p/ ...

随机推荐

  1. 带gcd大数模板

    int ten[4] = {1,10,100,1000}; typedef struct BigNumber { int d[1200]; BigNumber(string s) { int i, j ...

  2. Atcoder grand 025 组合数学塔涂色 贪心走路博弈

    A 略 B 题意:给你N个数(3e5) 每个数可以是0,a,b,a+b(3e5) 但是总数加起来要是定值K(18e10) 问总方法数mod 998244353 解: 把a+b的看成是一个a加上一个b的 ...

  3. WPF手动触发路由事件

    MouseButtonEventArgs args = , MouseButton.Left); args.RoutedEvent = UIElement.MouseLeftButtonDownEve ...

  4. 【模板】AC自动机加强版

    题目大意:给定 N 个模式串和一个文本串,求每个模式串在文本串中出现的次数. 题解:文本串在自动机上匹配的过程中,记录下自动机上每一个状态被访问的次数.对于访问到的节点 i,则状态 i 的后缀中存在的 ...

  5. SpringMVC 向页面传值-Map、Model和ModelMap

    除了使用ModelAndView方式外.还可以使用Map.Model和ModelMap来向前台页面传值 使用后面3种方式,都是在方法参数中,指定一个该类型的参数.例如: Java代码 @Request ...

  6. 【shell】截取字符串前面文字

    例如:有一个文件test.txt,里面有这些数据. meiguounix232 faguounix ribenunix zhongguounixtaobao hanguounixbaba 现在我想截取 ...

  7. requestAnimationFram

    window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画.该方法需要传入一个回调函数作为参数,该回调函数会 ...

  8. Pycharm中文显示异常

    pycharm2019,中文显示乱码异常,配置了encoding为utf8还是不行,需要设置备用字体 原因是某些英文字体库不支持非英文字符,无法显示 设置fallback字体 File-setting ...

  9. Vue-Router的简单使用

    Vue-Router的最简单使用 1.先注册路由 2.将路由注册到VM组件中 3.定义组件 4.页面定义跳转路径 <!DOCTYPE html> <html> <head ...

  10. js-点击tab按钮,同一页面显示不同的内容

    效果: html: JS: css: .tabs-two{ .two{ display: inline-block; font-size:14px; height: 17px; font-weight ...