您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库

时间:2022-07-05 11:33:10  来源:  作者:crossoverJie
用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库

 

前言

在之前实现的 JSON 解析器中当时只实现了将一个 JSON 字符串转换为一个 JSONObject,并没有将其映射为一个具体的 struct;如果想要获取值就需要先做断言将其转换为 map 或者是切片再来获,会比较麻烦。

 decode, err := gjson.Decode(`{"glossary":{"title":"example glossary","age":1}}`)
 assert.Nil(t, err)
 glossary := v["glossary"].(map[string]interface{})
 assert.Equal(t, glossary["title"], "example glossary")
 assert.Equal(t, glossary["age"], 1)

但其实转念一想,部分场景我们甚至我们只需要拿到 JSON 中的某个字段的值,这样还需要先声明一个 struct 会略显麻烦。

经过查询发现已经有了一个类似的库来解决该问题,https://Github.com/tidwall/gjson 并且 star 数还很多(甚至名字都是一样的),说明这样的需求大家还是很强烈的。

于是我也打算增加类似的功能,使用方式如下:

用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库

 

最后还加上了一个四则运算的功能。

面向对象的方式操作 JSON

因为功能类似,所以我参考了 tidwall 的 API 但去掉一些我觉得暂时用不上的特性,并调整了一点语法。

当前这个版本只能通过确定的 key 加上 . 点符号访问数据,如果是数组则用 [index] 的方式访问下标。 [] 符号访问数组我觉得要更符合直觉一些。

以下是一个包含多重嵌套 JSON 的访问示例:

str := `
{
"name": "bob",
"age": 20,
"skill": {
    "lang": [
        {
            "go": {
                "feature": [
                    "goroutine",
                    "channel",
                    "simple",
                    true
                ]
            }
        }
    ]
}
}`

name := gjson.Get(str, "name")
assert.Equal(t, name.String(), "bob")

age := gjson.Get(str, "age")
assert.Equal(t, age.Int(), 20)

assert.Equal(t, gjson.Get(str,"skill.lang[0].go.feature[0]").String(), "goroutine")
assert.Equal(t, gjson.Get(str,"skill.lang[0].go.feature[1]").String(), "channel")
assert.Equal(t, gjson.Get(str,"skill.lang[0].go.feature[2]").String(), "simple")
assert.Equal(t, gjson.Get(str,"skill.lang[0].go.feature[3]").Bool(), true)

这样的语法使用个人觉得还是满符合直觉的,相信对使用者来说也比较简单。

返回值参考了 tidwall 使用了一个 Result 对象,它提供了多种方法可以方便的获取各种类型的数据

func (r Result) String() string
func (r Result) Bool() bool
func (r Result) Int() int
func (r Result) Float() float64
func (r Result) Map() map[string]interface{}
func (r Result) Array() *[]interface{}
func (r Result) Exists() bool

比如使用 Map()/Array() 这两个函数可以将 JSON 数据映射到 map 和切片中,当然前提是传入的语法返回的是一个合法 JSONObject 或数组。

实现原理

在实现之前需要先定义一个基本语法,主要支持以下四种用法:

  • 单个 key 的查询:Get(json,"name")
  • 嵌套查询: Get(json,"obj1.obj2.obj3.name")
  • 数组查询:Get(json,"obj.array[0]")
  • 数组嵌套查询:Get(json,"obj.array[0].obj2.obj3[1].name")

语法很简单,符合我们日常接触到语法规则,这样便可以访问到 JSON 数据中的任何一个值。

其实实现过程也不复杂,我们已经在上一文中实现将 JSON 字符串转换为一个 JSONObject 了。

这次只是额外再解析刚才定义的语法为 token,然后解析该 token 的同时再从生成好的 JSONObject 中获取数据。

最后在解析完 token 时拿到的 JSONObject 数据返回即可。


用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库

 

我们以这段查询代码为例:

首先第一步是对查询语法做词法分析,最终得到下图的 token。

用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库

 

在词法分析过程中也可以做简单的语法校验;比如如果包含数组查询,并不是以 ] 符号结尾时就抛出语法错误。

用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库

 

接着我们遍历语法的 token。如下图所示:

用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库

 

每当遍历到 token 类型为 Key 时便从当前的 JSONObject 对象中获取数据,并用获取到的值替覆盖为当前的 JSONObject。

其中每当遇到 . [ ] 这样的 token 时便消耗掉,直到我们将 token 遍历完毕,这时将当前 JSONObject 返回即可。

在遍历过程中当遇到非法格式时,比如 obj_list[1.] 便会返回一个空的 JSONObject。

语法校验这点其实也很容易办到,因为根据我们的语法规则,Array 中的 index 后一定紧接的是一个 EndArray,只要不是一个 EndArray 便能知道语法不合法了。

有兴趣的可以看下解析过程的源码:

https://github.com/crossoverJie/gjson/blob/cfbca51cc9bc0c77e6cb9c9ad3f964b2054b3826/json.go#L46

对 JSON 做四则运算

 str := `{"name":"bob", "age":10,"magic":10.1, "score":{"math":[1,2]}}`
 result := GetWithArithmetic(str, "(age+age)*age+magic")
 assert.Equal(t, result.Float(), 210.1)
 result = GetWithArithmetic(str, "(age+age)*age")
 assert.Equal(t, result.Int(), 200)

 result = GetWithArithmetic(str, "(age+age) * age + score.math[0]")
 assert.Equal(t, result.Int(), 201)

 result = GetWithArithmetic(str, "(age+age) * age - score.math[0]")
 assert.Equal(t, result.Int(), 199)

 result = GetWithArithmetic(str, "score.math[1] / score.math[0]")
 assert.Equal(t, result.Int(), 2)

最后我还扩展了一下语法,可以支持对 JSON 数据中的整形(int、float)做四则运算,虽然这是一个小众需求,但做完我觉得还挺有意思的,目前在市面上我还没发现有类似功能的库,可能和小众需求有关。

其中核心的四则运算逻辑是由之前写的脚本解释器提供的:

https://github.com/crossoverJie/gscript

用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库

 

单独提供了一个函数,传入一个四则运算表达式返回计算结果。

由于上一版本还不支持 float,所以这次专门适配了一下。

限于篇幅,更多关于这个四则运算的实现逻辑会在后面继续分享。

总结

至此算是我第一次利用编译原理的知识解决了一点特定领域问题,在大学以及工作这些年一直觉得编译原理比较高深,所以内心一直是抗拒的,但经过这段时间的学习和实践慢慢的也掌握到了一点门道。

不过目前也只是冰山一角,后面的编译原理后端更是要涉及到计算机底层知识,所以依然任重而道远。

已上都是题外话,针对于这个库我也会长期维护;为了能达到生产的使用要求,尽量提高了单测覆盖率,目前是98%。

也欢迎大家使用,提 bug。

后面会继续优化,比如支持转义字符、提高性能等。

感兴趣的朋友请持续关注: https://github.com/crossoverJie/gjson



Tags:JSON   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
如何在Rust中操作JSON,你学会了吗?
sonic-rs ​还具有一些额外的方法来进行惰性评估和提高速度。例如,如果我们想要一个 JSON​ 字符串文字,我们可以在反序列化时使用 LazyValue​ 类型将其转换为一个仍然带有斜...【详细内容】
2024-02-27  Search: JSON  点击:(51)  评论:(0)  加入收藏
.NET配置文件大揭秘:轻松读取JSON、XML、INI和环境变量
概述:.NET中的IConfiguration接口提供了一种多源读取配置信息的灵活机制,包括JSON、XML、INI文件和环境变量。通过示例,清晰演示了从这些不同源中读取配置的方法,使配置获取变得...【详细内容】
2023-12-28  Search: JSON  点击:(94)  评论:(0)  加入收藏
使用 Mapstructure 解析 Json,你学会了吗?
背景前几天群里的小伙伴问了一个这样的问题:图片其实质就是在面对 value 类型不确定的情况下,怎么解析这个 json?我下意识就想到了 [mapstructure](https://github.com/mitchel...【详细内容】
2023-12-27  Search: JSON  点击:(159)  评论:(0)  加入收藏
JSON非常慢:这里有更快的替代方案!
是的,你没听错!JSON,这种在网络开发中普遍用于数据交换的格式,可能正在拖慢我们的应用程序。在速度和响应性至关重要的世界里,检查 JSON 的性能影响至关重要。在这篇博客中,深入探...【详细内容】
2023-11-21  Search: JSON  点击:(260)  评论:(0)  加入收藏
Json格式弊端及优化方案
Json介绍Json(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于前后端数据传输和存储。它使用简洁的文本格式来表示结构化的数据,易于阅读和编写,并且可以被多种编...【详细内容】
2023-11-13  Search: JSON  点击:(301)  评论:(0)  加入收藏
web服务器json-serve详解
简介JSON-Server 是一个 Node 模块,运行 Express 服务器,你可以指定一个 json 文件作为 api 的数据源。一、安装 JSON-Serve (Install JSON Server)使用 npm 或 yarn 工具安装...【详细内容】
2023-11-09  Search: JSON  点击:(324)  评论:(0)  加入收藏
Python文件操作:JSON、CSV、TSV、Excel和Pickle文件序列化
文件操作是Python编程的重要部分,它涉及处理各种文件格式,包括JSON、CSV、TSV、Excel和Pickle。一、JSON文件操作1.1 什是JSON?JSON(JavaScript Object Notation)是一种轻量级数...【详细内容】
2023-10-26  Search: JSON  点击:(77)  评论:(0)  加入收藏
程序开发中是使用XML还是使用JSON作为数据传输格式好?
在程序开发中,使用XML还是JSON作为传输对象是一个常见的问题。两者都是常用的数据交换格式,但在不同的情况下,使用XML或JSON可能会有不同的优势和适用性。XML(可扩展标记语言)是...【详细内容】
2023-10-24  Search: JSON  点击:(26)  评论:(0)  加入收藏
程序开发中使用XML还是JSON作为数据传输格式好?
在程序开发中,使用XML还是JSON作为传输对象是一个常见的问题。两者都是常用的数据交换格式,但在不同的情况下,使用XML或JSON可能会有不同的优势和适用性。XML(可扩展标记语言)是...【详细内容】
2023-10-24  Search: JSON  点击:(193)  评论:(0)  加入收藏
Python开发者的宝典:CSV和JSON数据处理技巧大公开!
在Python中处理CSV和JSON数据时,需要深入了解这两种数据格式的读取、写入、处理和转换方法。下面将详细介绍如何在Python中处理CSV和JSON数据,并提供一些示例和最佳实践。CSV...【详细内容】
2023-10-17  Search: JSON  点击:(221)  评论:(0)  加入收藏
▌简易百科推荐
JavaScript的异步编程常见模式
在JavaScript中,异步编程是一种处理长时间运行操作(如网络请求或I/O操作)的常见方式。它允许程序在等待这些操作完成时继续执行其他任务,从而提高应用程序的响应性和性能。JavaS...【详细内容】
2024-04-12  靳国梁    Tags:JavaScript   点击:(11)  评论:(0)  加入收藏
17 个你需要知道的 JavaScript 优化技巧
你可能一直在使用JavaScript搞开发,但很多时候你可能对它提供的最新功能并不感冒,尽管这些功能在无需编写额外代码的情况下就可以解决你的问题。作为前端开发人员,我们必须了解...【详细内容】
2024-04-03  前端新世界  微信公众号  Tags:JavaScript   点击:(7)  评论:(0)  加入收藏
你不可不知的 15 个 JavaScript 小贴士
在掌握如何编写JavaScript代码之后,那么就进阶到实践——如何真正地解决问题。我们需要更改JS代码使其更简单、更易于阅读,因为这样的程序更易于团队成员之间紧密协...【详细内容】
2024-03-21  前端新世界  微信公众号  Tags:JavaScript   点击:(29)  评论:(0)  加入收藏
又出新JS运行时了!JS运行时大盘点
Node.js是基于Google V8引擎的JavaScript运行时,以非阻塞I/O和事件驱动架构为特色,实现全栈开发。它跨平台且拥有丰富的生态系统,但也面临安全性、TypeScript支持和性能等挑战...【详细内容】
2024-03-21  前端充电宝  微信公众号  Tags:JS   点击:(29)  评论:(0)  加入收藏
构建一个通用灵活的JavaScript插件系统?看完你也会!
在软件开发中,插件系统为应用程序提供了巨大的灵活性和可扩展性。它们允许开发者在不修改核心代码的情况下扩展和定制应用程序的功能。本文将详细介绍如何构建一个灵活的Java...【详细内容】
2024-03-20  前端历险记  微信公众号  Tags:JavaScript   点击:(23)  评论:(0)  加入收藏
对JavaScript代码压缩有什么好处?
对JavaScript代码进行压缩主要带来以下好处: 减小文件大小:通过移除代码中的空白符、换行符、注释,以及缩短变量名等方式,可以显著减小JavaScript文件的大小。这有助于减少网页...【详细内容】
2024-03-13  WangLiwen    Tags:JavaScript   点击:(13)  评论:(0)  加入收藏
跨端轻量JavaScript引擎的实现与探索
一、JavaScript 1.JavaScript语言JavaScript是ECMAScript的实现,由ECMA 39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。ECMAScript发展史: 2.JavaScript...【详细内容】
2024-03-12  京东云开发者    Tags:JavaScript   点击:(13)  评论:(0)  加入收藏
面向AI工程的五大JavaScript工具
令许多人惊讶的是,一向在Web开发领域中大放异彩的JavaScript在开发使用大语言模型(LLM)的应用程序方面同样大有价值。我们在本文中将介绍面向AI工程的五大工具,并为希望将LLM...【详细内容】
2024-02-06    51CTO  Tags:JavaScript   点击:(60)  评论:(0)  加入收藏
JS小知识,使用这6个小技巧,避免过多的使用 if 语句
最近在重构我的代码时,我注意到早期的代码使用了太多的 if 语句,达到了我以前从未见过的程度。这就是为什么我认为分享这些可以帮助我们避免使用过多 if 语句的简单技巧很重要...【详细内容】
2024-01-30  前端达人  今日头条  Tags:JS   点击:(64)  评论:(0)  加入收藏
18个JavaScript技巧:编写简洁高效的代码
本文翻译自 18 JavaScript Tips : You Should Know for Clean and Efficient Code,作者:Shefali, 略有删改。在这篇文章中,我将分享18个JavaScript技巧,以及一些你应该知道的示例...【详细内容】
2024-01-30  南城大前端  微信公众号  Tags:JavaScript   点击:(80)  评论:(0)  加入收藏
站内最新
站内热门
站内头条