当前位置: 首页 > news >正文

Golang的json解析--Gjson库的使用举例

目录

简介

安装

原生的json解析 

Gjson使用举例

基本使用

键路径

使用示例

其他资源

简介

在 Golang 中,解析 JSON 数据是一项非常常见的任务。Go提供了标准的JSON包,可以轻松地将JSON数据序列化和反序列化。但是,在使用标准JSON包解析大型复杂JSON结构时,可能存在些许不足,例如代码冗余,性能瓶颈等问题。针对这些问题,目前有许多优秀的JSON解析框架,GJSON是其中一个很不错的选择。

GJSON 是一个 Go 包,提供了一种 高效 和 简单 的方式来从 JSON 文档中提取值。它具有如 一行检索、点号路径语法、迭代 和 解析 JSON 行 等特性。

本文将详细讲解如何使用GJSON框架解析JSON数据。

安装

GJSON模块可以通过go get命令来安装。

go get -u github.com/tidwall/gjson

原生的json解析 

以解析豆瓣接口https://api.douban.com/v2/movie/new_movies,返回的数据如下:

{"subjects": [{"rating": {"max": 10,"average": 7.1,"details": {"1": 16.0,"3": 135.0,"2": 56.0,"5": 102.0,"4": 122.0},"stars": "35","min": 0},"genres": ["\u5267\u60c5","\u559c\u5267","\u52a8\u4f5c"],"title": "\u76df\u519b\u6562\u6b7b\u961f","casts": [{"avatars": {"small": "https://img9.doubanio.com\/view\/celebrity\/m\/public\/p1371934661.95.jpg","large": "https://img9.doubanio.com\/view\/celebrity\/m\/public\/p1371934661.95.jpg","medium": "https://img9.doubanio.com\/view\/celebrity\/m\/public\/p1371934661.95.jpg"},"name_en": "Henry Cavill","name": "\u4ea8\u5229\u00b7\u5361\u7ef4\u5c14","alt": "https:\/\/movie.douban.com\/celebrity\/1044713\/","id": "1044713"},{"avatars": {"small": "https://img3.doubanio.com\/view\/celebrity\/m\/public\/p1607496406.37.jpg","large": "https://img3.doubanio.com\/view\/celebrity\/m\/public\/p1607496406.37.jpg","medium": "https://img3.doubanio.com\/view\/celebrity\/m\/public\/p1607496406.37.jpg"},"name_en": "Eiza Gonz\u00e1lez","name": "\u827e\u838e\u00b7\u5188\u8428\u96f7\u65af","alt": "https:\/\/movie.douban.com\/celebrity\/1233270\/","id": "1233270"}],"durations": ["120\u5206\u949f"],"collect_count": 25322,"mainland_pubdate": "2024-05-24","has_video": false,"original_title": "The Ministry of Ungentlemanly Warfare","subtype": "movie","directors": [{"avatars": {"small": "https://img1.doubanio.com\/view\/celebrity\/m\/public\/p47189.jpg","large": "https://img1.doubanio.com\/view\/celebrity\/m\/public\/p47189.jpg","medium": "https://img1.doubanio.com\/view\/celebrity\/m\/public\/p47189.jpg"},"name_en": "Guy Ritchie","name": "\u76d6\u00b7\u91cc\u5947","alt": "https:\/\/movie.douban.com\/celebrity\/1025148\/","id": "1025148"}],"pubdates": ["2024-04-18(\u4e2d\u56fd\u9999\u6e2f)","2024-04-19(\u7f8e\u56fd)","2024-05-24(\u4e2d\u56fd\u5927\u9646)"],"year": "2024","images": {"small": "https://img9.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p2908456064.jpg","large": "https://img9.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p2908456064.jpg","medium": "https://img9.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p2908456064.jpg"},"alt": "https:\/\/movie.douban.com\/subject\/34971728\/","id": "34971728"}],"title": "\u8c46\u74e3\u7535\u5f71\u65b0\u7247\u699c"
}

使用golang原始的方式,将响应体JSON反序列化为一个字典(map),以便于访问其中的数据。

body, err := io.ReadAll(res.Body)if err != nil {l.Errorf("Failed to read response body:", err)return nil, err}//格式化输出json//var str bytes.Buffer//_ = json.Indent(&str, []byte(body), "", "    ")//l.Debugf("formated: ", str.String())var keyVal map[string]interface{}err = json.Unmarshal(body, &keyVal)if err != nil {l.Errorf("Failed to extract key value:", err)}//l.Debug(keyValue)var hot types.HotItemvar responseData []types.HotItemlist_, ok := keyVal["subjects"].([]interface{})if ok {for _, item := range list_ {itemMap, ok := item.(map[string]interface{})if ok {//l.Debug(itemMap)hot.Id = itemMap["id"].(string)hot.Title = itemMap["title"].(string)tmp := itemMap["images"].(map[string]interface{})hot.Cover = l.svcCtx.Config.MvConf.Referer + tmp["small"].(string)hot.Rate = itemMap["rating"].(map[string]interface{})["average"].(float64)}responseData = append(responseData, hot)}}

 示例如下:

func (l *HotMovieLogic) HotMovie(req *types.HotMovieReq) (resp *types.HotMovieResp, err error) {// todo: add your logic here and delete this linetype Request struct {Req    types.HotMovieReqApiKey string `json:"apikey"`}req_ := Request{Req:    *req,ApiKey: l.svcCtx.Config.MvConf.ApiKey,}l.Debug(req_)url := l.svcCtx.Config.MvConf.BaseUrl + "/movie/in_theaters"res, err_ := httpc.Do(l.ctx, http.MethodPost, url, req_)if err_ != nil {l.Error(err_)return nil, err_}defer res.Body.Close()body, err := io.ReadAll(res.Body)if err != nil {l.Errorf("Failed to read response body:", err)return nil, err}//格式化输出json//var str bytes.Buffer//_ = json.Indent(&str, []byte(body), "", "    ")//l.Debugf("formated: ", str.String())var keyVal map[string]interface{}err = json.Unmarshal(body, &keyVal)if err != nil {l.Errorf("Failed to extract key value:", err)}//l.Debug(keyValue)var hot types.HotItemvar responseData []types.HotItemlist_, ok := keyVal["subjects"].([]interface{})if ok {for _, item := range list_ {itemMap, ok := item.(map[string]interface{})if ok {//l.Debug(itemMap)hot.Id = itemMap["id"].(string)hot.Title = itemMap["title"].(string)tmp := itemMap["images"].(map[string]interface{})hot.Cover = l.svcCtx.Config.MvConf.Referer + tmp["small"].(string)hot.Rate = itemMap["rating"].(map[string]interface{})["average"].(float64)}responseData = append(responseData, hot)}}//t := reflect.TypeOf(keyVal["count"])//l.Debugf("Type: %v\n", t)resp = &types.HotMovieResp{Code:    0,Message: res.Status,Data:    responseData,Count:   int(keyVal["count"].(float64)),Start:   int(keyVal["start"].(float64)),Total:   int(keyVal["total"].(float64)),Title:   keyVal["title"].(string),}return resp, nil
}

Gjson使用举例

基本使用

package mainimport ("fmt""github.com/tidwall/gjson"
)func main() {json := `{"name":{"first":"li","last":"dj"},"age":18}`lastName := gjson.Get(json, "name.last")fmt.Println("last name:", lastName.String())age := gjson.Get(json, "age")fmt.Println("age:", age.Int())email := gjson.Get(json, "email")// json 中不存在该字段时,String为空串,Int为0,即返回想要转换的类型的零值fmt.Println("email:", email.String())
}

使用很简单,只需要传入 JSON 串和要读取的键路径即可。注意一点细节,因为gjson.Get()函数实际上返回的是gjson.Result类型,我们要调用其相应的方法进行转换对应的类型。如上面的String()Int()方法。 

获取值

Get 函数搜索 JSON 中指定的路径。路径以点号分隔,如 "name.last" 或 "age"。一旦找到值,会立即返回。

package mainimport "github.com/tidwall/gjson"const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`func main() {value := gjson.Get(json, "name.last")println(value.String())
}

键路径

键路径实际上是以.分隔的一系列键。gjson支持在键中包含通配符*和?,*匹配任意多个字符,?匹配单个字符,例如ca*可以匹配cat、cate、cake等以ca开头的键,ca?只能匹配cat、cap等以ca开头且后面只有一个字符的键。

数组使用键名 + . + 索引(索引从 0 开始)的方式读取元素,如果键pets对应的值是一个数组,那么pets.0读取数组的第一个元素,pets.1读取第二个元素。

数组长度使用键名 + . + #获取,例如pets.#返回数组pets的长度。

如果键名中出现.,那么需要使用\进行转义。

路径语法

以下是对路径语法的快速概述,更多信息请参阅 GJSON 语法。

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

{"name": {"first": "Tom", "last": "Anderson"},"age":37,"children": ["Sara","Alex","Jack"],"fav.movie": "Deer Hunter","friends": [{"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},{"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},{"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}]
}

取值示例: 

"name.last"          >> "Anderson"
"age"                >> 37
"children"           >> ["Sara","Alex","Jack"]
"children.#"         >> 3
"children.1"         >> "Alex"
"child*.2"           >> "Jack"
"c?ildren.0"         >> "Sara"
"fav\.movie"         >> "Deer Hunter"
"friends.#.first"    >> ["Dale","Roger","Jane"]
"friends.1.last"     >> "Craig"

结果类型

GJSON 支持 JSON 类型 stringnumberbool 和 null。数组和对象以它们的原始 JSON 类型返回。

Result 类型持有这些之一:

bool, 对应 JSON 布尔值
float64, 对应 JSON 数字
string, 对应 JSON 字符串字面量
nil, 对应 JSON null

获取对象数组中的元素

var nitem types.NewItemvar responseData []types.NewItemlist_ := gjson.GetBytes(body, "subjects").Array()for _, item := range list_ {nitem.Id = item.Get("id").String()nitem.Title = item.Get("title").String()nitem.Cover = l.svcCtx.Config.MvConf.Referer + item.Get("images.small").String()nitem.Rate = item.Get("rating.average").Float()nitem.Pubdate = item.Get("pubdates.0").String()responseData = append(responseData, nitem)}

使用示例

解析豆瓣影视接口返回的数据:

func (l *NewMovieLogic) NewMovie(req *types.NewMovieReq) (resp *types.NewMovieResp, err error) {type Request struct {Req    types.NewMovieReqApiKey string `json:"apikey"`}req_ := Request{Req:    *req,ApiKey: l.svcCtx.Config.MvConf.ApiKey,}l.Debug(req_)url := l.svcCtx.Config.MvConf.BaseUrl + "/movie/new_movies"res, err_ := httpc.Do(l.ctx, http.MethodPost, url, req_)if err_ != nil {l.Error(err_)return nil, err_}defer res.Body.Close()body, err := io.ReadAll(res.Body)if err != nil {l.Errorf("Failed to read response body:", err)return nil, err}//格式化输出json//var str bytes.Buffer//_ = json.Indent(&str, []byte(body), "", "    ")//l.Debugf("formated: ", str.String())//l.Debug(keyValue)var nitem types.NewItemvar responseData []types.NewItemlist_ := gjson.GetBytes(body, "subjects").Array()for _, item := range list_ {nitem.Id = item.Get("id").String()nitem.Title = item.Get("title").String()nitem.Cover = l.svcCtx.Config.MvConf.Referer + item.Get("images.small").String()nitem.Rate = item.Get("rating.average").Float()nitem.Pubdate = item.Get("pubdates.0").String()responseData = append(responseData, nitem)}//t := reflect.TypeOf(keyVal["count"])//l.Debugf("Type: %v\n", t)if len(list_) != 0 {resp = &types.NewMovieResp{Code:    0,Message: res.Status,Data:    responseData,Count:   len(list_),Start:   0,Total:   len(list_),Title:   gjson.GetBytes(body, "title").String(),}} else {resp = &types.NewMovieResp{Code:    0,Message: res.Status,Data:    responseData,Count:   0,Start:   0,Total:   0,Title:   "",}}return resp, nil
}

其他资源

Go 语言 gjson对Json数据进行操作_go gjson-CSDN博客

34.Go操作JSON利器之gjson包_golang gjson-CSDN博客

GitCode - 全球开发者的开源社区,开源代码托管平台

相关文章:

Golang的json解析--Gjson库的使用举例

目录 简介 安装 原生的json解析 Gjson使用举例 基本使用 键路径 使用示例 其他资源 简介 在 Golang 中,解析 JSON 数据是一项非常常见的任务。Go提供了标准的JSON包,可以轻松地将JSON数据序列化和反序列化。但是,在使用标准JSON包…...

基于Langchain构建本地大型语言模型(LLM)问答系统的经验分享

基于Langchain构建本地大型语言模型(LLM)问答系统的经验分享 https://download.csdn.net/download/xziyuan/89334371?spm1001.2101.3001.9500 最近,我一直在探索如何利用Langchain来构建一个本地的大型语言模型问答系统。在这个过程中&…...

对抗式生成模仿学习(GAIL)

目录 1 预先基础知识 1.1 对抗生成网络(GAN) 1.1.1 基本概念 1.1.2 损失函数 1.1.2.1 固定G,求解令损失函数最大的D 1.1.2.2 固定D,求解令损失函数最小的G 1.2 对抗式生成模仿学习特点 2 对抗式生成模仿学习(…...

信息系统项目管理师 | 新一代信息技术

关注WX:CodingTechWork 物联网 定义 The Internet of Things是指通过信息传感设备,按约定的协议,将任何物品与互联网连接,进行信息交互和通信,以实现智能化识别。定位、跟踪、监控和管理的一种网络。物联网主要解决…...

安全宣传咨询日活动向媒体投稿记住这个投稿好方法

在信息爆炸的时代,作为单位的信息宣传员,我肩负着将每一次重要活动,特别是像“安全宣传咨询日”这样的公益活动,有效传达给公众的重任。这份工作看似简单,实则充满了挑战,尤其是在我初涉此领域时,那段曲折而又难忘的投稿经历,至今记忆犹新。 初探投稿之海,遭遇重重困难 起初,我…...

第7章:系统架构设计基础知识-软件架构风格

由于历史原因,研究者和工程人员对Sofiware Architecture(简称SA)的翻译不尽相同,其软件的“体系结构”和“架构”具有相同的含义。 系统架构其实就是系统的结构,系统架构设计其实就是要给相关利益方说清楚通过什么样的结构来解决需求中功能和…...

自制调色小工具给图片加滤镜,修改图片红、绿、蓝通道及亮度,修改图片颜色

上篇: 上篇我们给地图添加了锐化、模糊等滤镜,这篇来写一个小工具给图片调色。 调色比锐化等滤镜要简单许多,直接拿到像素值修改即可。不需要用到卷积核。。。(*^▽^*) 核心原理就是图像结构,使用context.getImageData获取图像像…...

【Redis】java客户端(SpringData和jedis)

https://www.oz6.cn/articles/58 https://www.bilibili.com/video/BV1cr4y1671t/?p16 redis官网客户端介绍&#xff1a;https://redis.io/docs/latest/develop/connect/clients/ jedis maven引入依赖 <dependencies><!--引入Jedis依赖--><dependency><…...

大数据安全经典面试题及回答(上)

目录 一、大数据安全的主要挑战及应对策略 二、大数据安全中的“五个V”及其影响 三、在Hadoop集群中实施数据加密的步骤和注意事项 四、在大数据环境中实施访问控制和身份认证 五、大数据环境中数据备份和恢复的策略 六、大数据处理过程中保护用户隐私的策略 七、大数据…...

vi/vim使用命令

你是否在编辑文件时以为键盘坏了&#xff0c;为什么不能删除呢&#xff0c;为什么不能敲代码呢&#xff0c;当你初识vi&#xff0c;会觉得这个东西设计很难用&#xff0c;这篇教程带你熟练得用上这款经典的工具&#xff0c;当你熟练了这款工具就会真正体会到高效率打码 Vi 是在…...

webpack打包gz文件,nginx开启gzip压缩

wepback配置 webpack4配合"compression-webpack-plugin": "^6.1.2"打包压缩gz chain.plugin("compression").use(new CompressionPlugin({test: /\.js$|\.html$|\.css$/,threshold: 10240, // 超过10KB的压缩deleteOriginalAssets: false,// 保…...

微服务开发与实战Day11 - 微服务面试篇

一、分布式事务 1. CAP定理 1998年&#xff0c;加州大学的计算机科学及Eric Brewer提出&#xff0c;分布式系统有三个指标&#xff1a; Consistency&#xff08;一致性&#xff09;Availability&#xff08;可用性&#xff09;Partition tolerance&#xff08;分区容错性&am…...

基于Spring Boot+VUE职称评审管理系统

1管理员功能模块 管理员登录&#xff0c;通过填写注册时输入的用户名、密码、角色进行登录&#xff0c;如图1所示。 图1管理员登录界面图 管理员登录进入职称评审管理系统可以查看首页、个人中心、用户管理、评审员管理、省份管理、评审条件管理、职称申请管理、结果公布管理、…...

MySQL 基本语法讲解及示例(上)

第一节&#xff1a;MySQL的基本操作 1. 创建数据库 在 MySQL 中&#xff0c;创建数据库的步骤如下&#xff1a; 命令行操作 打开 MySQL 命令行客户端或连接到 MySQL 服务器。 输入以下命令创建一个数据库&#xff1a; CREATE DATABASE database_name;例如&#xff0c;创建一…...

6.18作业

完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&#xff…...

Excel文件转换为HTML文件

文章目录 前言安装python包python代码 前言 将一个Excel文件转换为HTML文件 安装python包 使用pandas和openpyxl库来实现这个功能 pip install pandas openpyxlpython代码 1、首先使用tkinter库中的filedialog模块弹出一个对话框来选择要转换的Excel文件 2、使用pandas库…...

MySQL数据库入门

1、MySQL概述 MySQL官方网站 https://www.mysql.com/downloads/ MySQL被Oracle公司收购了&#xff0c;作者又重新编写了一个开源的数据库管理系统&#xff0c;Mariadb 2、MySQL产品&版本 2、数据库在网站架构中的角色 LAMP LNMP网站架构 3、安装MySQL-基于yum 查…...

vue element-ui 下拉框 以及 input 限制输入,小数点后保留两位 界面设计案例 和 例子:支持mp4和m3u8视频播放

vue input 限制输入&#xff0c;小数点后保留两位 以及 图片垂直居中显示 和 分享 git 小技巧-CSDN博客文章浏览阅读430次&#xff0c;点赞5次&#xff0c;收藏4次。error:Your local changes to the following files would be overwritten by merge:_error: your local change…...

Python基础用法 之 运算符

1.算数运算符 符号作用说明举例加与“”相同 - 减与“-”相同*乘 与“ ”相同 9*218/除 与“ ”相同 9/24.5 、6/32.0//求商&#xff08;整数部分&#xff09; 两个数据做除法的 商 9//24%取余&#xff08;余数部分&#xff09; 是两个数据做除法的 余数 9%21**幂、次方2**…...

事务所管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;客户管理&#xff0c;评论管理&#xff0c;基础数据管理&#xff0c;公告信息管理 客户账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;律师管理&#xff0…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...