前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Go中解析JSON

Go中解析JSON

原创
作者头像
ruochen
发布于 2021-12-05 15:06:18
发布于 2021-12-05 15:06:18
3.4K0
举报
安装

要使用gjson,先要安装go环境并执行go get:

代码语言:txt
AI代码解释
复制
$ go get -u github.com/tidwall/gjson

以上命令会检索并下载该库到Go环境中。

Get函数获取值

Get在json中搜索指定的路径。路径用点语法表示,比如“name.last"或“age"。这个函数需要提供格式正规和有效的json值。无效的json不会引起panic,但它可能返回意外的结果。当找到值后立即返回。

代码语言:txt
AI代码解释
复制
package main
代码语言:txt
AI代码解释
复制
import "github.com/tidwall/gjson"
代码语言:txt
AI代码解释
复制
const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
代码语言:txt
AI代码解释
复制
func main() {
代码语言:txt
AI代码解释
复制
    result := gjson.Get(json, "name.last")
代码语言:txt
AI代码解释
复制
    println(result.String())
代码语言:txt
AI代码解释
复制
}

output

代码语言:txt
AI代码解释
复制
Prichard

还有用于处理JSON字节切片的GetBytes(https://links.jianshu.com/go?to=https%3A%2F%2Fwww.ctolib.com%2Fgjson.html%23working-

with-bytes) 函数。

path语法

path是由点分隔的一系列键。key可以包含特殊的通配符'*'和'?'。要访问数组值,请使用索引作为键。要获取数组中的元素数量或访问子路径,请使用'#'字符。点和通配符可以用'\'转义。

代码语言:txt
AI代码解释
复制
{
代码语言:txt
AI代码解释
复制
  "name": {"first": "Tom", "last": "Anderson"},
代码语言:txt
AI代码解释
复制
  "age":37,
代码语言:txt
AI代码解释
复制
  "children": ["Sara","Alex","Jack"],
代码语言:txt
AI代码解释
复制
  "fav.movie": "Deer Hunter",
代码语言:txt
AI代码解释
复制
  "friends": [
代码语言:txt
AI代码解释
复制
    {"first": "James", "last": "Murphy"},
代码语言:txt
AI代码解释
复制
    {"first": "Roger", "last": "Craig"}
代码语言:txt
AI代码解释
复制
  ]
代码语言:txt
AI代码解释
复制
}
代码语言:txt
AI代码解释
复制
"name.last"          >> "Anderson"
代码语言:txt
AI代码解释
复制
"age"                >> 37
代码语言:txt
AI代码解释
复制
"children"           >> ["Sara","Alex","Jack"]
代码语言:txt
AI代码解释
复制
"children.#"         >> 3
代码语言:txt
AI代码解释
复制
"children.1"         >> "Alex"
代码语言:txt
AI代码解释
复制
"child*.2"           >> "Jack"
代码语言:txt
AI代码解释
复制
"c?ildren.0"         >> "Sara"
代码语言:txt
AI代码解释
复制
"fav\.movie"         >> "Deer Hunter"
代码语言:txt
AI代码解释
复制
"friends.#.first"    >> ["James","Roger"]
代码语言:txt
AI代码解释
复制
"friends.1.last"     >> "Craig"

查询一个数组:

代码语言:txt
AI代码解释
复制
`friends.#[last="Murphy"].first` >> "James"
结果类型

GJSON支持json类型字符串,数字,bool和null。数组和对象作为原始json类型返回。

Result类型包含以下类型之一:

代码语言:txt
AI代码解释
复制
bool, for JSON booleans
代码语言:txt
AI代码解释
复制
float64, for JSON numbers
代码语言:txt
AI代码解释
复制
string, for JSON string literals
代码语言:txt
AI代码解释
复制
nil, for JSON null

要直接访问该值:

代码语言:txt
AI代码解释
复制
result.Type    // 可能是String, Number, True, False, Null, or JSON
代码语言:txt
AI代码解释
复制
result.Str     // 保存string
代码语言:txt
AI代码解释
复制
result.Num     // 保存float64
代码语言:txt
AI代码解释
复制
result.Raw     // 保存 raw json
代码语言:txt
AI代码解释
复制
result.Index   // json中原始值的索引,0表示索引未知

result有很多函数:

代码语言:txt
AI代码解释
复制
result.Value() interface{}
代码语言:txt
AI代码解释
复制
result.Int() int64
代码语言:txt
AI代码解释
复制
result.Uint() uint64
代码语言:txt
AI代码解释
复制
result.Float() float64
代码语言:txt
AI代码解释
复制
result.String() string
代码语言:txt
AI代码解释
复制
result.Bool() bool
代码语言:txt
AI代码解释
复制
result.Array() []gjson.Result
代码语言:txt
AI代码解释
复制
result.Map() map[string]gjson.Result
代码语言:txt
AI代码解释
复制
result.Get(path string) Result

result.Value返回一个interface{},需要断言,是以下类型之一:

代码语言:txt
AI代码解释
复制
boolean >> bool
代码语言:txt
AI代码解释
复制
number  >> float64
代码语言:txt
AI代码解释
复制
string  >> string
代码语言:txt
AI代码解释
复制
null    >> nil
代码语言:txt
AI代码解释
复制
array   >> []interface{}
代码语言:txt
AI代码解释
复制
object  >> map[string]interface{}

result.Array()返回一个数组。如果result代表一个不存在的值,那么将返回一个空数组。如果result不是一个JSON数组,返回值将是一个包含一个结果的数组。

Get获取嵌套数组值

假设你想要以下json中的所有lastName对应值:

代码语言:txt
AI代码解释
复制
{
代码语言:txt
AI代码解释
复制
  "programmers": [
代码语言:txt
AI代码解释
复制
    {
代码语言:txt
AI代码解释
复制
      "firstName": "Janet", 
代码语言:txt
AI代码解释
复制
      "lastName": "McLaughlin", 
代码语言:txt
AI代码解释
复制
    }, {
代码语言:txt
AI代码解释
复制
      "firstName": "Elliotte", 
代码语言:txt
AI代码解释
复制
      "lastName": "Hunter", 
代码语言:txt
AI代码解释
复制
    }, {
代码语言:txt
AI代码解释
复制
      "firstName": "Jason", 
代码语言:txt
AI代码解释
复制
      "lastName": "Harold", 
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
  ]
代码语言:txt
AI代码解释
复制
}

您将使用路径“programmers.#.lastName“像这样:

代码语言:txt
AI代码解释
复制
result := gjson.Get(json, "programmers.#.lastName")
代码语言:txt
AI代码解释
复制
for _,name := range result.Array() {
代码语言:txt
AI代码解释
复制
    println(name.String())
代码语言:txt
AI代码解释
复制
}

你也可以查询数组中的对象:

代码语言:txt
AI代码解释
复制
name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`)
代码语言:txt
AI代码解释
复制
println(name.String())  // 输出 "Elliotte"
parse和Get

有一个Parse(json)函数将执行简单的解析,result.Get(path)将搜索结果。例如,以下代码都将返回相同的结果:

代码语言:txt
AI代码解释
复制
gjson.Parse(json).Get("name").Get("last")
代码语言:txt
AI代码解释
复制
gjson.Get(json, "name").Get("last")
代码语言:txt
AI代码解释
复制
gjson.Get(json, "name.last")
检查值是否存在

有时你只是想知道一个值是否存在。

代码语言:txt
AI代码解释
复制
value := gjson.Get(json, "name.last")
代码语言:txt
AI代码解释
复制
if !value.Exists() {
代码语言:txt
AI代码解释
复制
    println("no last name")
代码语言:txt
AI代码解释
复制
} else {
代码语言:txt
AI代码解释
复制
    println(value.String())
代码语言:txt
AI代码解释
复制
}
代码语言:txt
AI代码解释
复制
// 或一步到位
代码语言:txt
AI代码解释
复制
if gjson.Get(json, "name.last").Exists(){
代码语言:txt
AI代码解释
复制
    println("has a last name")
代码语言:txt
AI代码解释
复制
}
反序列化到map
代码语言:txt
AI代码解释
复制
m, ok := gjson.Parse(json).Value().(map[string]interface{})
代码语言:txt
AI代码解释
复制
if !ok{
代码语言:txt
AI代码解释
复制
    // 不是map
代码语言:txt
AI代码解释
复制
}
使用字节

如果json存在[]byte切片中,有一个

GetBytes

函数。首选使用:Get(string(data), path)

代码语言:txt
AI代码解释
复制
var json []byte = ...
代码语言:txt
AI代码解释
复制
result := gjson.GetBytes(json, path)

如果你使用gjson.GetBytes(json, path)函数,想避免将result.raw转换到[]byte,可以使用如下模式:

代码语言:txt
AI代码解释
复制
var json []byte = ...
代码语言:txt
AI代码解释
复制
result := gjson.GetBytes(json, path)
代码语言:txt
AI代码解释
复制
var raw []byte
代码语言:txt
AI代码解释
复制
if result.Index > 0 {
代码语言:txt
AI代码解释
复制
    raw = json[result.Index:result.Index+len(result.Raw)]
代码语言:txt
AI代码解释
复制
} else {
代码语言:txt
AI代码解释
复制
    raw = []byte(result.Raw)
代码语言:txt
AI代码解释
复制
}

这种方式不为原json分配子切片。这个方法使用result.Index属性,这是原始数据在原始json中的位置。result.Index的值可能等于0,这种情况下result.Raw被转成[]byte。

性能

与encoding/json, ffjson, EasyJSON和jsonparser,对比 GJSON的基准测试:

代码语言:txt
AI代码解释
复制
BenchmarkGJSONGet-8                 15000000           333 ns/op           0 B/op          0 allocs/op
代码语言:txt
AI代码解释
复制
BenchmarkGJSONUnmarshalMap-8          900000          4188 ns/op        1920 B/op         26 allocs/op
代码语言:txt
AI代码解释
复制
BenchmarkJSONUnmarshalMap-8           600000          8908 ns/op        3048 B/op         69 allocs/op
代码语言:txt
AI代码解释
复制
BenchmarkJSONUnmarshalStruct-8        600000          9026 ns/op        1832 B/op         69 allocs/op
代码语言:txt
AI代码解释
复制
BenchmarkJSONDecoder-8                300000         14339 ns/op        4224 B/op        184 allocs/op
代码语言:txt
AI代码解释
复制
BenchmarkFFJSONLexer-8               1500000          3156 ns/op         896 B/op          8 allocs/op
代码语言:txt
AI代码解释
复制
BenchmarkEasyJSONLexer-8             3000000           938 ns/op         613 B/op          6 allocs/op
代码语言:txt
AI代码解释
复制
BenchmarkJSONParserGet-8             3000000           442 ns/op          21 B/op          0 allocs/op

使用的json文档:

代码语言:txt
AI代码解释
复制
{
代码语言:txt
AI代码解释
复制
  "widget": {
代码语言:txt
AI代码解释
复制
    "debug": "on",
代码语言:txt
AI代码解释
复制
    "window": {
代码语言:txt
AI代码解释
复制
      "title": "Sample Konfabulator Widget",
代码语言:txt
AI代码解释
复制
      "name": "main_window",
代码语言:txt
AI代码解释
复制
      "width": 500,
代码语言:txt
AI代码解释
复制
      "height": 500
代码语言:txt
AI代码解释
复制
    },
代码语言:txt
AI代码解释
复制
    "image": { 
代码语言:txt
AI代码解释
复制
      "src": "Images/Sun.png",
代码语言:txt
AI代码解释
复制
      "hOffset": 250,
代码语言:txt
AI代码解释
复制
      "vOffset": 250,
代码语言:txt
AI代码解释
复制
      "alignment": "center"
代码语言:txt
AI代码解释
复制
    },
代码语言:txt
AI代码解释
复制
    "text": {
代码语言:txt
AI代码解释
复制
      "data": "Click Here",
代码语言:txt
AI代码解释
复制
      "size": 36,
代码语言:txt
AI代码解释
复制
      "style": "bold",
代码语言:txt
AI代码解释
复制
      "vOffset": 100,
代码语言:txt
AI代码解释
复制
      "alignment": "center",
代码语言:txt
AI代码解释
复制
      "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
代码语言:txt
AI代码解释
复制
    }
代码语言:txt
AI代码解释
复制
  }
代码语言:txt
AI代码解释
复制
}    

执行的搜索操作:

代码语言:txt
AI代码解释
复制
widget.window.name
代码语言:txt
AI代码解释
复制
widget.image.hOffset
代码语言:txt
AI代码解释
复制
widget.text.onMouseUp

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
暂无评论
推荐阅读
Spring Security 4 Hibernate整合 注解和xml例子(带源码)
下一篇文章:Spring Security 4 整合Hibernate Bcrypt密码加密(带源码)
明明如月学长
2021/08/27
1.1K0
Spring Security 4 Hibernate整合 注解和xml例子(带源码)
SpringBoot+SpringSecurity+JWT实RESTfulAPI权限控制
根据文章内容总结的摘要
林老师带你学编程
2018/01/04
4.2K0
SpringBoot+SpringSecurity+JWT实RESTfulAPI权限控制
重学SpringBoot3-集成Spring Security(二)
在上一节中,我们讨论了Spring Security 的认证功能,通过实现用户身份验证来确保系统的安全性。而在本节中,我们将深入了解授权机制,如何控制用户在系统中可以访问的资源和操作。
CoderJia
2024/10/18
3800
重学SpringBoot3-集成Spring Security(二)
springmvc、spring、hibernate整合示例
在mysql数据库中建立一个user表,已对user的增删改查为例,整合springmvc、spring、hibernate。 1.web.xml中的配置:①spring监听器;②spring mvc的servlet;③字符编码过滤器。 <!-- spring 监听器的配置 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <c
yawn
2018/03/14
1.2K0
Spring Security 4 使用@PreAuthorize,@PostAuthorize, @Secured, EL实现方法安全(带源码)
【相关已翻译的本系列其他文章,点击分类里面的spring security 4】
明明如月学长
2021/08/27
2.7K0
Spring Security 4 基于角色的登录例子(带源码)
原文网址: http://websystique.com/spring-security/spring-security-4-role-based-login-example/
明明如月学长
2021/08/27
1.2K0
Spring+SpringMVC+Hibernate简单整合(转)
SpringMVC又一个漂亮的web框架,他与Struts2并驾齐驱,Struts出世早而占据了一定优势,下面同样做一个简单的应用实例,介绍SpringMVC的基本用法,接下来的博客也将梳理一下Struts2和SpringMVC的一些异同,通过梳理和旧知识的联系,让学习的成本变低,花很短的时间就可以了解一门貌似新的技术,其实本质没变。
yaohong
2019/09/11
8630
Spring Security 4 自定义登录表单 注解和XML例子(带源码)
上一篇文章: Spring Security 4 Hello World 基于注解 和 XML 例子  下一篇:Spring Security 4 退出 示例
明明如月学长
2021/08/27
8520
SpringBoot入门建站全系列(十二)Spring Security使用token做认证
Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。
品茗IT
2019/08/14
3.4K0
Spring Security和JWT实现登录授权认证
IUserService的实现类,注册时会将用户权限设置为ROLE_USER,同时将密码使用BCrypt加密
朝雨忆轻尘
2019/06/18
4.7K2
Spring MVC 4 文件上传下载 Hibernate+MySQL例子 (带源码)
【本系列其他教程正在陆续翻译中,点击分类:spring 4 mvc 进行查看。源码下载地址在文章末尾。】
明明如月学长
2021/08/27
6460
重学SpringBoot3-集成Spring Security(四)
在现代应用开发中,安全性和数据管理是两大重要模块。Spring Security 提供了全面的安全解决方案,而 Spring Data JPA 则简化了与数据库的交互。将两者结合,可以在保护应用的同时,轻松实现基于用户身份的访问控制、权限管理和安全的数据存储操作。
CoderJia
2024/10/20
3320
重学SpringBoot3-集成Spring Security(四)
SpringBoot整合SpringSecurity简单实现登入登出从零搭建
技术栈 : SpringBoot + SpringSecurity + jpa + freemark ,完整项目地址 : https://github.com/EalenXie/spring-security-login
EalenXie
2020/09/21
5.3K0
SpringBoot整合SpringSecurity简单实现登入登出从零搭建
Spring整合HibernateJPA
现如今的ORM框架还是比较多的比如Hibernate,TopLink以及OpenJPA等等,为了简化ORM框架的使用,JPA随之产生。
Java鱼头
2022/12/01
3981
React.js 集成 Spring Boot 开发 Web 应用
使用文档: https://nowa-webpack.github.io/nowa/
一个会写诗的程序员
2018/08/17
3.2K0
React.js  集成 Spring Boot 开发 Web 应用
spring之整合Hibernate
这里需要说明的是table="SH_BOOK"中SH是表的前缀,我们在写hql语句时不用带上,系统会自动识别。
西西嘛呦
2020/08/26
4770
spring之整合Hibernate
struts2+spring+hibernate整合步骤(1)
struts2、hibernate、spring所需jar包 struts-core-2.x.x.jar ----struts核心包 xwork-core-2.x.x.jar -----身体ruts在其撒很难过构建 ognl-2.6.x.jar ----对象导航语言 freemarker-2.3.x.jar ------struts2的ui标签的模板使用 commons-fileupload-1.2.x.jar ----文件上传组件 2.1.6版本后需加入此文件 str
Java帮帮
2018/03/15
7380
SpringMVC+Hibernate4
 1) /SpringMVCHibernate4/src/main/webapp/view/index.jsp
py3study
2020/01/08
3620
Spring Security 4 Hello World 基于注解 和 XML 例子(带源码)
原文:http://websystique.com/spring-security/spring-security-4-hello-world-annotation-xml-example/
明明如月学长
2021/08/27
5180
详细介绍SpringBoot整合SpringSecurity
  本文我们来详细给小伙伴们介绍下SpringBoot整合SpringSecurity的过程,用到的技术为:SpringBoot2.2.1+SpringSecurity+SpringDataJPA+jsp来整合。
用户4919348
2019/12/11
1.1K0
详细介绍SpringBoot整合SpringSecurity
推荐阅读
相关推荐
Spring Security 4 Hibernate整合 注解和xml例子(带源码)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档