JSON

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
  • JSON 具有自我描述性,更易理解

JSON的组成

JSON 数据的书写格式是:

key : value

JSON 值可以是:

  • 数字(整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或 false)
  • 数组(在中括号中)
  • 对象(在大括号中)
  • null

JSON 解析器实现原理

JSON 解析器从本质上来说就是根据 JSON 文法规则创建的状态机

输入是一个 JSON 字符串,输出是一个Table。

状态机具体如下图所示:


具体代码实现

JsonLoader = {}
i = 1
json = ''function JsonLoader:getChar(str, i)--print(str, i)return string.sub(str, i, i)end-- 跳过空格、换行、制表符、回车
function JsonLoader:skipWhitespace()while (JsonLoader:getChar(json, i) == ' 'or JsonLoader:getChar(json, i) == '\n'or JsonLoader:getChar(json, i) == '\t'or JsonLoader:getChar(json, i) == '\r') doi = i + 1endend-- 处理逗号
function JsonLoader:eatComma()if (JsonLoader:getChar(json, i) ~= ',') thenprint('Expected ,')endi = i + 1end-- 处理冒号
function JsonLoader:eatColon()if (JsonLoader:getChar(json, i) ~= ':') thenprint('Expected :')endi = i + 1
end-- 是否为16进制数
function JsonLoader:isHexadecimal(char)return (char >= '0' and char <= '9') or (string.lower(char) >= 'a' and string.lower(char) <= 'f')
end-- 获取字符串
function JsonLoader:parseString()--print('parse String: ', i , 'times')if (JsonLoader:getChar(json, i) == '"') theni = i + 1local result = ""while (JsonLoader:getChar(json, i) ~= '"') doif (JsonLoader:getChar(json, i) == '\\') thenchar = JsonLoader:getChar(json, i+1)if ( char == '"'or char == '\\'or char == '/'or char == 'b'or char == 'f'or char == 'n'or char == 'r'or char == 't') thenresult = result..chari = i + 1elseif (char == 'u') thenif (isHexadecimal(getChar(json, i+2))and isHexadecimal(JsonLoader:getChar(json, i+3))and isHexadecimal(JsonLoader:getChar(json, i+4))and isHexadecimal(JsonLoader:getChar(json, i+5))) thenresult = result .. string.sub(json,i+2, i+5)i = i + 5endendelseresult = result .. JsonLoader:getChar(json, i)-- 如果字符串为数字,进行转换if tonumber(result) ~= nil thenresult = tonumber(result)endendi = i + 1endi = i + 1--print("parse String res: ", result)return resultendreturn nil
end-- 解析数值
function JsonLoader:parseNumber()--print('parse Number: ', i , 'times')start = iif JsonLoader:getChar(json, i) == '-' theni = i + 1end-- 解析数字,跳过首位0if (JsonLoader:getChar(json, i) == '0') theni = i +1elseif (JsonLoader:getChar(json, i) >= '1' and JsonLoader:getChar(json, i) <= '9') theni = i + 1while(JsonLoader:getChar(json, i) >= '0' and JsonLoader:getChar(json, i) <= '9') doi = i + 1endend-- 检测小数if(JsonLoader:getChar(json, i) == '.') theni = i + 1while(JsonLoader:getChar(json, i) >= '0' and JsonLoader:getChar(json, i) <= '9') doi = i + 1endend-- 检测科学计数法if(JsonLoader:getChar(json, i) == 'e' or JsonLoader:getChar(json, i) == 'E') theni = i + 1if(JsonLoader:getChar(json, i) == '-' or JsonLoader:getChar(json, i) == '+') theni = i + 1endwhile(JsonLoader:getChar(json, i) >= '0' and JsonLoader:getChar(json, i) <= '9') doi = i + 1endendif (i > start) then--print('parse Number res: ', tonumber(string.sub(json, start, i-1)))return tonumber(string.sub(json, start, i-1))endreturn nilend-- 解析关键字
function JsonLoader:parseKeyword(name, value)if (string.sub(json, i, i + #name) == name) theni = i + #namereturn valueendend-- 解析对象
function JsonLoader:parseObject()--print('parse Object: ', i , 'times')if (JsonLoader:getChar(json, i)== '{') theni = i + 1JsonLoader:skipWhitespace()local result = {}initial = truewhile (JsonLoader:getChar(json, i) ~= '}') doif (not initial) thenJsonLoader:eatComma()JsonLoader:skipWhitespace()endlocal key = JsonLoader:parseString()JsonLoader:skipWhitespace()JsonLoader:eatColon()local value = JsonLoader:parseValue()--print(key, value)result[key] = valueinitial = falseJsonLoader:skipWhitespace()end-- move to the next character of '}'i = i + 1--for k,  v in pairs(result) do--    print('202', k , v)----end--print('parse Object res: ', result)return resultend
end-- 解析值 递归调用其他方法
function JsonLoader:parseValue()--print('parse Value: ', i , 'times')JsonLoader:skipWhitespace()local valuelocal string = JsonLoader:parseString()local number = JsonLoader:parseNumber()local object = JsonLoader:parseObject()local array = JsonLoader:parseArray()local tr = JsonLoader:parseKeyword('true', true)local fl = JsonLoader:parseKeyword('false', false)local ni = JsonLoader:parseKeyword('null', nil)if string ~= nil thenreturn stringelseif number ~= nil thenreturn numberelseif object ~= nil thenreturn objectelseif array ~= nil thenreturn arrayelseif tr == true thenreturn trelseif fl == false thenreturn flelseif ni == nil thenreturn niend--local value = JsonLoader:parseString() or JsonLoader:parseNumber()--        or JsonLoader:parseObject() or JsonLoader:parseKeyword('true', true)--        or JsonLoader:parseKeyword('false', false) or JsonLoader:parseKeyword('null', nil)JsonLoader:skipWhitespace()--print('parse Value res:', value)return valueend-- 解析数组
function JsonLoader:parseArray()--print('parse Array: ', i , 'times')if (JsonLoader:getChar(json, i) == '[') theni = i + 1JsonLoader:skipWhitespace()local result = {}initial = truewhile (JsonLoader:getChar(json, i) ~= ']') doif (not initial) thenJsonLoader:eatComma()endlocal value = JsonLoader:parseValue()table.insert(result, value)initial = falseendi = i + 1return resultendreturn nilend-- 解析主函数
function JsonLoader:parse(input_file)print('start json parse')--res = {}--print(input_file)-- 读取文件local file = io.open(input_file, 'r')json = file:read('*a')file:close()print(json)-- json parse--print(JsonLoader:getChar(json, i))-- 判断首字符是否为'{'if (JsonLoader:getChar(json, i) == '{') theni = i + 1JsonLoader:skipWhitespace()-- 保存结果local result = {}initial = truewhile (JsonLoader:getChar(json, i) ~= '}')doif not initial thenJsonLoader:eatComma()JsonLoader:skipWhitespace()endlocal key = JsonLoader:parseString()JsonLoader:skipWhitespace()JsonLoader:eatColon()local value = JsonLoader:parseValue()--print("parse key- value: ",key, value)result[key] = value--print("273 res:", result[key])JsonLoader:skipWhitespace()initial = falseend-- move to the next character '{'i = i + 1return resultendreturn nil
endinput_file = 'a.json'local mytable = JsonLoader.parse(nil, input_file)print(' ---------------JsonLoader  res -------------')
print(type(mytable))
print(mytable[1].a)--[[
a.json
{"1":{"a":100}}output:
table
100
]]--

参考资料

JSON Parser with JavaScript

Lua 实现JSON解析器相关推荐

  1. 如何快速在Mac 安装 jq 命令行 JSON 解析器

    如何快速在Mac 安装 jq 命令行 JSON 解析器 jq 是什么 安装 过程如下 验证 jq 是什么 https://blog.csdn.net/shenhonglei1234/article/d ...

  2. spring boot2 修改默认json解析器Jackson为fastjson

    fastjson是阿里出的,尽管近年fasjson爆出过几次严重漏洞,但是平心而论,fastjson的性能的确很有优势,尤其是大数据量时的性能优势,所以fastjson依然是我们的首选:spring ...

  3. JavaScript语言精粹JSON解析器源码阅读

    1 // 这是一个用JavaScript编写JSON解析器的实现方案: 2 var jsonParser = (function() { 3 // 这是一个能把JSON文本解析成JavaScript数 ...

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

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

  5. 手把手教你实现一个 JSON 解析器!

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

  6. cJSON_译(C中的超轻量级JSON解析器)

    cJSON ANSI C中的超轻量级JSON解析器. 通行证 执照 版权所有(c)2009-2017 Dave Gamble和cJSON贡献者 特此免费授予获得此软件和相关文档文件("软件& ...

  7. json string 格式_自己动手实现一个简单的JSON解析器

    作者:田小波 原文:http://cnblogs.com/nullllun/p/8358146.html 1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数 ...

  8. json解析对应的value为null_徒手撸一个JSON解析器

      Java大联盟 致力于最高效的Java学习 关注 作者 | 田小波 cnblogs.com/nullllun/p/8358146.html1.背景JSON(JavaScript Object No ...

  9. string 转 json_手写Json解析器学习心得

    哦?从"{"开始,看来是个对象了! 一. 介绍 一周前,老同学阿立给我转了一篇知乎回答,答主说检验一门语言是否掌握的标准是实现一个Json解析器,网易游戏过去的Python入门培训 ...

最新文章

  1. 转:让kindle更好的支持pdf
  2. 【TensorFlow】ValueError: Shape must be rank 1 but is rank 0 for ' ’ with input shapes: [].问题
  3. 《训练指南》——6.9
  4. 图像和流媒体 -- 详解YUV数据格式
  5. 什么是对象,为什么要面向对象,怎么才能面向对象?
  6. 敏捷开发流程的8个步骤_敏捷开发——个体和互动高于流程和工具
  7. _Default同时存在于两个dll文件中的解决办法
  8. mysql中变量值得输出,几个比较重要的MySQL变量
  9. python基础学习笔记4--抽象
  10. Objective-C学习笔记(十八)——对象方法和类方法的声明,定义及调用
  11. 广州有这么一个无聊的人
  12. app推送怎么实现更好的效果?
  13. 003-photoshop快速去掉图片背景颜色、签名放到指定文档合成图片
  14. 人工蜂群算法求解TSP旅行商问题C++(2020.11.13)
  15. plt.imshow()中cmap参数控制颜色展示
  16. 每天一刷20200602
  17. python加油代码_python入门教程NO.5 用python写个自动选择加油站的小程序
  18. 基于大数据的健康未来
  19. (14)Delphi下利用JVCL组件包快速实现——解释Pascal语言的脚本引擎
  20. Axure PR9左侧页面概要元件母版不见了,在哪开启

热门文章

  1. java多选_java单选换多选
  2. 广东第二师范学院的btec计算机专业学习负担重吗?,广东第二师范学院怎么样 好不好...
  3. 苹果cmsv10泡泡影视自适应美化简洁高端简约模板
  4. Python爬虫:Scrapy的Crawler对象及扩展Extensions和信号Signals
  5. 简约黑白文艺范个人介绍PPT模板
  6. 2022高教社杯数学建模思路 - 案例:AdaBoost 算法
  7. 518抽奖软件教程之:开盘选房摇号
  8. Java8很香但还是想升级到Java11,教你怎么从Java8升级到Java11
  9. 跨立实验判断线段是否相交-POJ3304
  10. 轻松发送邮件! springboot,sendgrid和greenmail