golang动态JSON解析与编辑插件库gabs的使用
Golang动态JSON解析与编辑插件库gabs的使用
Gabs是一个用于处理Go中动态或未知JSON结构的小工具。它主要是对encoding/json
包提供的map[string]interface{}
对象层次结构进行导航的辅助包装器。
导入
使用Go模块导入:
import (
"github.com/Jeffail/gabs/v2"
)
不使用Go模块导入:
import (
"github.com/Jeffail/gabs"
)
解析和搜索JSON
jsonParsed, err := gabs.ParseJSON([]byte(`{
"outer":{
"inner":{
"value1":10,
"value2":22
},
"alsoInner":{
"value1":20,
"array1":[
30, 40
]
}
}
}`))
if err != nil {
panic(err)
}
var value float64
var ok bool
value, ok = jsonParsed.Path("outer.inner.value1").Data().(float64)
// value == 10.0, ok == true
value, ok = jsonParsed.Search("outer", "inner", "value1").Data().(float64)
// value == 10.0, ok == true
value, ok = jsonParsed.Search("outer", "alsoInner", "array1", "1").Data().(float64)
// value == 40.0, ok == true
gObj, err := jsonParsed.JSONPointer("/outer/alsoInner/array1/1")
if err != nil {
panic(err)
}
value, ok = gObj.Data().(float64)
// value == 40.0, ok == true
value, ok = jsonParsed.Path("does.not.exist").Data().(float64)
// value == 0.0, ok == false
exists := jsonParsed.Exists("outer", "inner", "value1")
// exists == true
exists = jsonParsed.ExistsP("does.not.exist")
// exists == false
遍历对象
jsonParsed, err := gabs.ParseJSON([]byte(`{"object":{"first":1,"second":2,"third":3}}`))
if err != nil {
panic(err)
}
// S是Search的简写
for key, child := range jsonParsed.S("object").ChildrenMap() {
fmt.Printf("key: %v, value: %v\n", key, child.Data().(float64))
}
遍历数组
jsonParsed, err := gabs.ParseJSON([]byte(`{"array":["first","second","third"]}`))
if err != nil {
panic(err)
}
for _, child := range jsonParsed.S("array").Children() {
fmt.Println(child.Data().(string))
}
输出:
first
second
third
在数组中搜索
如果你的结构包含数组,你必须在搜索中指定索引:
jsonParsed, err := gabs.ParseJSON([]byte(`{"array":[{"value":1},{"value":2},{"value":3}]`))
if err != nil {
panic(err)
}
fmt.Println(jsonParsed.Path("array.1.value").String())
将打印2
。
生成JSON
jsonObj := gabs.New()
// 或者使用gabs.Wrap(jsonObject)来处理现有的map[string]interface{}
jsonObj.Set(10, "outer", "inner", "value")
jsonObj.SetP(20, "outer.inner.value2")
jsonObj.Set(30, "outer", "inner2", "value3")
fmt.Println(jsonObj.String())
将打印:
{"outer":{"inner":{"value":10,"value2":20},"inner2":{"value3":30}}}
格式化输出:
fmt.Println(jsonObj.StringIndent("", " "))
将打印:
{
"outer": {
"inner": {
"value": 10,
"value2": 20
},
"inner2": {
"value3": 30
}
}
}
生成数组
jsonObj := gabs.New()
jsonObj.Array("foo", "array")
// 或者使用.ArrayP("foo.array")
jsonObj.ArrayAppend(10, "foo", "array")
jsonObj.ArrayAppend(20, "foo", "array")
jsonObj.ArrayAppend(30, "foo", "array")
fmt.Println(jsonObj.String())
将打印:
{"foo":{"array":[10,20,30]}}
按索引操作数组:
jsonObj := gabs.New()
// 创建一个长度为3的数组
jsonObj.ArrayOfSize(3, "foo")
jsonObj.S("foo").SetIndex("test1", 0)
jsonObj.S("foo").SetIndex("test2", 1)
// 创建一个嵌入的长度为3的数组
jsonObj.S("foo").ArrayOfSizeI(3, 2)
jsonObj.S("foo").Index(2).SetIndex(1, 0)
jsonObj.S("foo").Index(2).SetIndex(2, 1)
jsonObj.S("foo").Index(2).SetIndex(3, 2)
fmt.Println(jsonObj.String())
将打印:
{"foo":["test1","test2",[1,2,3]]}
转换回JSON
jsonParsedObj, _ := gabs.ParseJSON([]byte(`{
"outer":{
"values":{
"first":10,
"second":11
}
},
"outer2":"hello world"
}`))
jsonOutput := jsonParsedObj.String()
// 变成 `{"outer":{"values":{"first":10,"second":11}},"outer2":"hello world"}`
要序列化特定部分:
jsonOutput := jsonParsedObj.Search("outer").String()
// 变成 `{"values":{"first":10,"second":11}}`
合并两个容器
你可以将一个JSON结构合并到现有的结构中,冲突将被转换为JSON数组。
jsonParsed1, _ := ParseJSON([]byte(`{"outer":{"value1":"one"}}`))
jsonParsed2, _ := ParseJSON([]byte(`{"outer":{"inner":{"value3":"three"}},"outer2":{"value2":"two"}}`))
jsonParsed1.Merge(jsonParsed2)
// 变成 `{"outer":{"inner":{"value3":"three"},"value1":"one"},"outer2":{"value2":"two"}}`
数组合并:
jsonParsed1, _ := ParseJSON([]byte(`{"array":["one"]}`))
jsonParsed2, _ := ParseJSON([]byte(`{"array":["two"]}`))
jsonParsed1.Merge(jsonParsed2)
// 变成 `{"array":["one", "two"]}`
解析数字
Gabs在底层使用json
包,默认情况下会将所有数字值解析为float64
。如果需要解析Int
值,则应使用json.Decoder
:
sample := []byte(`{"test":{"int":10,"float":6.66}}`)
dec := json.NewDecoder(bytes.NewReader(sample))
dec.UseNumber()
val, err := gabs.ParseJSONDecoder(dec)
if err != nil {
t.Errorf("Failed to parse: %v", err)
return
}
intValue, err := val.Path("test.int").Data().(json.Number).Int64()
更多关于golang动态JSON解析与编辑插件库gabs的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang动态JSON解析与编辑插件库gabs的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang动态JSON解析与编辑插件库gabs使用指南
gabs是一个轻量级的Go语言库,用于动态解析、创建和操作JSON数据。它提供了简单直观的API来处理未知结构的JSON数据,特别适合需要动态处理JSON的场景。
安装gabs
go get github.com/Jeffail/gabs/v2
基本用法
1. 解析JSON
package main
import (
"fmt"
"github.com/Jeffail/gabs/v2"
)
func main() {
jsonStr := `{
"user": {
"name": "John",
"age": 30,
"skills": ["Go", "Python", "JavaScript"]
}
}`
// 解析JSON字符串
jsonParsed, err := gabs.ParseJSON([]byte(jsonStr))
if err != nil {
panic(err)
}
// 获取嵌套值
name := jsonParsed.Path("user.name").Data().(string)
age := jsonParsed.Path("user.age").Data().(float64)
firstSkill := jsonParsed.Path("user.skills.0").Data().(string)
fmt.Printf("Name: %s, Age: %.0f, First Skill: %s\n", name, age, firstSkill)
}
2. 创建JSON
func createJSON() {
jsonObj := gabs.New()
// 添加字段
jsonObj.Set("John", "user", "name")
jsonObj.Set(30, "user", "age")
jsonObj.Set([]string{"Go", "Python", "JavaScript"}, "user", "skills")
// 添加数组元素
jsonObj.ArrayAppend("Git", "user", "skills")
jsonObj.ArrayAppend("Docker", "user", "skills")
fmt.Println(jsonObj.StringIndent("", " "))
}
3. 修改JSON
func modifyJSON() {
jsonStr := `{"user":{"name":"John","age":30}}`
jsonParsed, _ := gabs.ParseJSON([]byte(jsonStr))
// 修改现有字段
jsonParsed.Set(31, "user", "age")
// 添加新字段
jsonParsed.Set(true, "user", "active")
// 删除字段
jsonParsed.Delete("user", "age")
fmt.Println(jsonParsed.String())
}
高级功能
1. 搜索JSON
func searchJSON() {
jsonStr := `{
"users": [
{"name": "John", "age": 30},
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 35}
]
}`
jsonParsed, _ := gabs.ParseJSON([]byte(jsonStr))
// 查找所有用户年龄
ages, _ := jsonParsed.Path("users.*.age").Children()
for _, age := range ages {
fmt.Println(age.Data())
}
// 查找特定用户
user := jsonParsed.Path("users.1").Data()
fmt.Printf("Second user: %v\n", user)
}
2. 合并JSON
func mergeJSON() {
json1 := `{"user":{"name":"John","age":30}}`
json2 := `{"user":{"age":31,"active":true},"company":"Tech Inc"}`
parsed1, _ := gabs.ParseJSON([]byte(json1))
parsed2, _ := gabs.ParseJSON([]byte(json2))
// 合并两个JSON对象
parsed1.Merge(parsed2)
fmt.Println(parsed1.StringIndent("", " "))
}
3. 处理JSON数组
func handleJSONArray() {
jsonObj := gabs.New()
// 创建数组
jsonObj.Array("users")
// 添加数组元素
jsonObj.ArrayAppend(map[string]interface{}{"name": "John", "age": 30}, "users")
jsonObj.ArrayAppend(map[string]interface{}{"name": "Alice", "age": 25}, "users")
// 修改数组元素
jsonObj.Set("Bob", "users", "1", "name")
jsonObj.Set(26, "users", "1", "age")
// 遍历数组
users, _ := jsonObj.S("users").Children()
for i, user := range users {
fmt.Printf("User %d: %v\n", i, user.Data())
}
}
错误处理
func handleErrors() {
jsonStr := `{"user":{"name":"John","age":30}}`
jsonParsed, err := gabs.ParseJSON([]byte(jsonStr))
if err != nil {
fmt.Println("JSON解析错误:", err)
return
}
// 安全访问可能不存在的路径
value := jsonParsed.Path("user.address.city").Data()
if value == nil {
fmt.Println("字段不存在")
} else {
fmt.Println(value)
}
}
性能考虑
gabs在便利性和性能之间做了权衡。对于高性能场景,建议使用标准库的encoding/json
与预定义的结构体。gabs更适合需要动态处理JSON的场景。
总结
gabs库提供了以下主要优势:
- 无需预定义结构体即可处理JSON
- 直观的路径访问语法
- 方便的JSON创建和修改API
- 强大的搜索和遍历功能
- 简单的JSON合并操作
对于需要动态处理JSON数据的Go应用程序,gabs是一个非常有价值的工具。