首页 > 其他分享 >Go--gjson

Go--gjson

时间:2023-12-06 17:12:14浏览次数:28  
标签:jsonStr gjson -- age Go last nets first

GJSON 是一个用于处理 JSON 数据的 Go 语言库。它提供了一些方便的功能,例如解析 JSON 字符串、查询 JSON 对象、生成 JSON 对象等

下载gjson: go get -u github.com/tidwall/gjson 

1、使用

传入 JSON 串和要读取的键路径,路径使用点号语法,如 "name.last "或 "age"。一旦找到值,就会立即返回。

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

例:

package main

import (
    "fmt"
    "github.com/tidwall/gjson"
)

func main() {
    //{
    //   "name": {"first": "Tom", "last": "Anderson"},
    //   "age":37,
    //   "children": ["Sara","Alex","Jack"],
    //   "friends": [
    //     {"first": "James", "last": "Murphy"},
    //     {"first": "Roger", "last": "Craig"}
    //   ]
    // }
    //设置json字符串
    jsonStr := `{"name": {"first": "Tom", "last": "Anderson"}, "age": 37, "children": ["Sara", "Alex", "Jack"], "friends": [{"first": "James", "last": "Murphy"}, {"first": "Roger", "last": "Craig"}]}`

    //获取数据
    name1 := gjson.Get(jsonStr, "name")          //默认返回的是gjson.Result类型,如果是直接打印,可直接使用,若是需进一步操作,建立转换成对应类型
    name2 := gjson.Get(jsonStr, "name").String() //从 jsonStr 中获取 "name" 字段的值,然后通过调用 .String() 方法,将获取到的值转换为字符串类型,如果 "name" 字段的值不是字符串类型,它会被转换为字符串
    name3 := gjson.Get(jsonStr, "name").Str      //也是从 jsonStr 中获取 "name" 字段的值,但是是直接获取该字段的值,没有进行类型转换,如果"name"字段的值不是字符串类型,则将保持原来的类型
    //如果确定 "name" 字段的值一定是字符串类型,那么使用 .Str 是更简洁的方式。如果不确定 "name" 字段的值是什么类型,或者想要确保它是一个字符串类型,那么使用 .String() 进行显式转换是更安全的选择。

    fmt.Printf("值类型:%T,值:%v\n", name1, name1)
    fmt.Printf("值类型:%T,值:%v\n", name2, name2)
    fmt.Printf("值类型:%T,值:%v\n", name3, name3)     //无法输出值是因为name" 是一个嵌套的 JSON 对象,而不是一个字符串
    first := gjson.Get(jsonStr, "name.first").Str //需要进一步获取值
    fmt.Printf("值类型:%T,值:%v\n", first, first)
}

输出结果:

值类型:gjson.Result,值:{"first": "Tom", "last": "Anderson"}
值类型:string,值:{"first": "Tom", "last": "Anderson"}
值类型:string,值:
值类型:string,值:Tom  

 

2、类型转换

方法 描述
String() 尝试将此值转换为string
Int() 尝试将此值转换为int64
Uint64() 尝试将此值转换为uint64
Float64() 尝试将此值转换为float64
Bool() 尝试将此值转换为布尔型

 

3、键路径

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

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

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

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

例(使用上面的json字符串):

    //设置json字符串
    jsonStr := `{"name": {"first": "Tom", "last": "Anderson"}, "age": 37, "children": ["Sara", "Alex", "Jack"], "friends": [{"first": "James", "last": "Murphy"}, {"first": "Roger", "last": "Craig"}]}`

    //获取数据
    fmt.Println("name.last:", gjson.Get(jsonStr, "name.last"))
    fmt.Println("age:", gjson.Get(jsonStr, "age"))
    fmt.Println("children:", gjson.Get(jsonStr, "children"))
    fmt.Println("children.#:", gjson.Get(jsonStr, "children.#"))           //返回数组的长度
    fmt.Println("children.1:", gjson.Get(jsonStr, "children.1"))           //读取数组下标为1的元素值(注意下标从0开始)
    fmt.Println("child*.2:", gjson.Get(jsonStr, "child*.2"))               //*匹配,再读取下标为2的元素值
    fmt.Println("c?ildren.0:", gjson.Get(jsonStr, "c?ildren.0"))           //也是匹配,不过只匹配一个字符,再读取下标为0的元素值
    fmt.Println("friends.#.first:", gjson.Get(jsonStr, "friends.#.first")) //如果数组#后还有内容,则以后面的路径读取数组中的每个元素,返回一个新的数组。所以该查询返回的数组所有friends的first字段组成
    fmt.Println("friends.1.first:", gjson.Get(jsonStr, "friends.1.first")) //读取friends第 2 个元素的last字段

输出结果:

name.last: Anderson
age: 37                           
children: ["Sara", "Alex", "Jack"]
children.#: 3                     
children.1: Alex
child*.2: Jack
c?ildren.0: Sara
friends.#.first: ["James","Roger"]
friends.1.first: Roger

 

3.1 数组

对于数组,gjson还支持按条件查询元素,#(条件)返回第一个满足条件的元素,#(条件)#返回所有满足条件的元素。括号内的条件可以有==!=<<=>>=,还有简单的模式匹配%(符合某个模式),!%(不符合某个模式):

package main

import (
    "fmt"
    "github.com/tidwall/gjson"
)

func main() {
    //设置json字符串
    var jsonStr = `{"name": {"first": "Tom", "last": "Anderson"}, "age": 37, "children": ["Sara", "Alex", "Jack"], "fav.movie": "Dear 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":{"first":"Tom", "last": "Anderson"},
    //    "age": 37,
    //    "children": ["Sara", "Alex", "Jack"],
    //"fav.movie": "Dear 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"]}
    //    ]
    //}

    //输出数据
    fmt.Println(gjson.Get(jsonStr, `friends.#(last="Murphy").first`))   //返回数组friends中第一个last为Murphy的元素;.first表示取出该元素的first字段返回
    fmt.Println(gjson.Get(jsonStr, `friends.#(last="Murphy")#.first`))  //返回数组friends中所有的last为Murphy的元素,然后读取它们的first字段放在一个数组中返回
    fmt.Println(gjson.Get(jsonStr, "friends.#(age>37)#.last"))          //返回数组friends中所有年龄大于 45 的元素,然后读取它们的last字段返回
    fmt.Println(gjson.Get(jsonStr, `friends.#(first%"D*").last`))       //返回数组friends中第一个first字段满足模式D*的元素,取出其last字段返回
    fmt.Println(gjson.Get(jsonStr, `friends.#(first!%"D*").last`))      //返回数组friends中第一个first字段**不**满足模式D*的元素,读取其last`字段返回
    fmt.Println(gjson.Get(jsonStr, `friends.#(nets.#(=="fb"))#.first`)) //这是个嵌套条件,friends.#(nets.#(=="fb"))#返回数组friends的元素的nets字段中有fb的所有元素,然后取出first字段返回
}

输出结果:

Dale
["Dale","Jane"]            
["Murphy","Craig","Murphy"]
Murphy                     
Craig                      
["Dale","Roger"] 

 

4、 一次获取多个值

调用gjson.Get()一次只能读取一个值,多次调用又比较麻烦,gjson提供了GetMany()可以一次读取多个值,返回一个数组[]gjson.Result

    //获取数据,使用3里面的字符串
    results := gjson.GetMany(jsonStr, "name", "age", "children.#", "friends.#.first")
    for _, result := range results {
        fmt.Println(result)
    }
    //输出结果
    //    {"first": "Tom", "last": "Anderson"}
    //    37
    //    3
    //    ["Dale","Roger","Jane"]

 

5、校验json

调用gjson.Get()时,gjson假设我们传入的 JSON 串是合法的。如果 JSON 非法也不会panic,这时会返回不确定的结果

gjson.Valid()检测 JSON 串是否合法:

if !gjson.Valid(json) {
  fmt.Println("error")
} else {
  fmt.Println("ok")
}

 

6、遍历

gjson.Get()方法返回一个gjson.Result类型的对象,json.Result提供了ForEach()方法用于遍历。该方法接受一个类型为func (key, value gjson.Result) bool的回调函数。遍历对象时keyvalue分别为对象的键和值;遍历数组时,value为数组元素,key为空(不是索引)。回调返回false时,遍历停止。

    results := gjson.Get(jsonStr, "friends")            //获取初始数据,3里面的字符串
    results.ForEach(func(k, result gjson.Result) bool { //遍历,一般不需要k,可用_忽略
        first := gjson.Get(result.Raw, "first") //可以再次根据键路径获取更为详细的数据
        fmt.Printf("k:%v,v:%v\n", k, results)   //输出键值
        fmt.Println(first)                      //输出friends数组里的first元素值
        return true
    })

输出结果:

k:0,v:[{"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"]}]
Dale
k:1,v:[{"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"]}]
Roger
k:2,v:[{"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"]}]
Jane
PS D:\Users\W9010315\GolandProjects\test> go run .\gjson.go
k:0,v:[{"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"]}]
Dale                                                                                                                                                                                                                          
k:1,v:[{"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"]}]
Roger                                                                                                                                                                                                                         
k:2,v:[{"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"]}]
Jane   

 

 

 

本文参考:https://darjun.github.io/2020/03/22/godailylib/gjson/

 

标签:jsonStr,gjson,--,age,Go,last,nets,first
From: https://www.cnblogs.com/Xinenhui/p/17879819.html

相关文章

  • 博客三
    前言本次博客涵盖了Java题目的主要知识点,包括以下内容:面向对象的基础知识:介绍了类和对象的基本概念、构造方法、访问权限和成员变量。面向对象的设计原则:重点讲解了继承和组合这两个重要的设计原则。要求学生对这两种原则有深入的理解,并能根据实际需求选择合适的设计方式。异常处......
  • 四.JAVA循环
    四.JAVA循环,方法‘\t’:制表符//TODO:代办事项for循环for(初始化语句A;boolean类型表达式B;更改表达式){ 循环体;D}执行顺序:for-->A-->B  |false:循环结束  |true:-->D-->C-->B死循环:boolean类型值恒为真for循环中boolean类......
  • 软件测试/人工智能|Python逻辑运算符如何灵活使用
    前言当初学者探索Python编程时,理解逻辑运算符是掌握编程逻辑和决策流程的重要一环。逻辑运算符允许我们对多个条件进行组合,以便进行更复杂的逻辑判断。让我们深入了解Python中常用的逻辑运算符及其使用方法。逻辑运算符逻辑运算符一般用来解决当有多个关系条件需要判断时使用,......
  • 无涯教程-Erlang - find函数
    此方法用于查找Map中是否存在特定键。find-语法find(key,map)key  - 这是需要转换为Map的列表。Map- 这是需要在其中搜索键的Map。find-返回值如果在Map上找到键,则返回值。-module(helloLearnfk).-export([start/0]).start()->Lst1=[{"a",1},{"b"......
  • 企业设备资产管理看板,助力企业资产智能化管理
    企业数字化是当今时代的趋势,越来越多的企业开始意识到数字化转型的重要性。而在企业数字化的过程中,一个关键的方面就是企业设备资产管理。企业所拥有的设备资产是企业顺利运营的重要保障,然而,传统的设备资产管理方式往往存在着不高效、不准确的问题。在传统的设备资产管理方式下,企业......
  • Android安卓App应用程序开发后如何运行到真机上?
    Hello各位同学们,各位安卓app开发者们大家好,我是咕噜铁蛋!。当你完成一个令人兴奋的安卓应用程序后,将它成功地运行在真机上是至关重要的一步。毕竟,只有在真实设备上测试和调试,我们才能真正了解应用程序在用户手中的表现。在本文中,我将与大家分享一些简单的步骤和宝贵的经验,帮助你顺利......
  • linux使用tail,grep查看文件,提示配到二进制文件 (标准输入)
    环境centos7.9背景最近在linux下使用cat,tail等查看日志时会报《配到二进制文件(标准输入)》,然后就没有任何输出,通常这些日志是中文英文混打印的如使用vi进日志后能查看中文格式的内容原因那是因为在Linux系统中,使用tail和grep命令来查找中文格式的log时,遇到《Binaryfil......
  • 固态硬盘的优势是什么?
    固态硬盘的优势是什么?1、重量轻体积小。固态硬盘相比机械硬盘在体积上更小,重量更轻。一般来说,台式机的机械硬盘的尺寸在3.5英寸,而SATA接口的固态硬盘的尺寸仅有2.5英寸,而M.2接口的固态硬盘体积更小,只有U盘的大小。2、静音。由于固态硬盘没有机械马达,类似于U盘,因此在固态硬盘工作......
  • 软件测试/人工智能|Python赋值运算符如何灵活使用
    前言赋值运算符是使用=为运算符号,将运算符左侧的数据或表达式的结果,保存到运算符左侧的标识符中。在使用赋值运算符时,运算符右侧可以是任意类型的数据,但左侧必须是一个变量,否则会报错。除普通的赋值运算符外,赋值运算符还可以和算术运算符组合成为复合赋值运算符。赋值运算符不仅仅......
  • 进一步探索智慧医疗新模式,圆心科技上市前景广阔
    在政策、监管的多方推动下,我国智慧医疗形势一片大好,数据显示,2022年我国智医疗应用规模约为780.5亿元,到2023年国内智慧医疗应用规模可达到936.6亿元,未来市场份额也将进一步扩已经成为了众多资本眼中的香饽饽。不久前,我国知名医疗健康公司北京圆心科技就完成了多轮融资,为其赴......