做电影网站成本,wordpress页面无法编辑器,银川市做网站的公司,厦门个人网站建设目录
简介
安装
原生的json解析
Gjson使用举例
基本使用
键路径
使用示例
其他资源
简介
在 Golang 中#xff0c;解析 JSON 数据是一项非常常见的任务。Go提供了标准的JSON包#xff0c;可以轻松地将JSON数据序列化和反序列化。但是#xff0c;在使用标准JSON包…目录
简介
安装
原生的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_theatersres, 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 (fmtgithub.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/gjsonconst 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 类型 string, number, bool 和 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_moviesres, 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 - 全球开发者的开源社区,开源代码托管平台