golang动态JSON解析与编辑插件库gabs的使用

Golang动态JSON解析与编辑插件库gabs的使用

Gabs Logo

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

1 回复

更多关于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库提供了以下主要优势:

  1. 无需预定义结构体即可处理JSON
  2. 直观的路径访问语法
  3. 方便的JSON创建和修改API
  4. 强大的搜索和遍历功能
  5. 简单的JSON合并操作

对于需要动态处理JSON数据的Go应用程序,gabs是一个非常有价值的工具。

回到顶部