«

Go 处理 JSON 教程 - 使用 gabs 包来处理 JSON 数据

在上篇博文 《Go 处理 JSON 教程 - 如何创建和解析 JSON 数据》 中,介绍了如何使用 Go 标准库中的 encoding/json,来创建和解析 JSON 数据。

这篇文章,将介绍一个更方便的 Go 三方库 gabs ,它对 json.Marshal/json.Unmarshalmap[string]interface{} 做了一个更好的良好封装,用来处理 动态或不确定JSON 数据。

一、如何安装

go get github.com/Jeffail/gabs  

二、如何使用

gabs 封装了几个函数,可以非常方便的用来处理解析和创建 JSON。

1、解析和搜索 JSON

核心函数是: ParseJSON, PathSearch,示例如下:

package main

import (  
    "fmt"
    "github.com/Jeffail/gabs"
)

func main() {  
    jsonParsed, _ := gabs.ParseJSON([]byte(`{
    "outter":{
        "inner":{
            "value1":10,
            "value2":22
        },
        "alsoInner":{
            "value1":20
        }
    }
    }`))

    var value float64
    var ok bool

    value, ok = jsonParsed.Path("outter.inner.value1").Data().(float64)
    fmt.Println("value ==", value, ", ok ==", ok)
    // value == 10.0, ok == true

    value, ok = jsonParsed.Search("outter", "inner", "value1").Data().(float64)
    fmt.Println("value ==", value, ", ok ==", ok)
    // value == 10.0, ok == true

    value, ok = jsonParsed.Path("does.not.exist").Data().(float64)
    fmt.Println("value ==", value, ", ok ==", ok)
    // value == 0.0, ok == false

    exists := jsonParsed.Exists("outter", "inner", "value1")
    fmt.Println("exists ==", exists)
    // exists == true

    exists = jsonParsed.Exists("does", "not", "exist")
    fmt.Println("exists ==", exists)
    // exists == false

    exists = jsonParsed.ExistsP("does.not.exist")
    fmt.Println("exists ==", exists)
    // exists == false
}

2、遍历对象

核心函数:ChildrenMap

jsonParsed, _ := gabs.ParseJSON([]byte(`{"object":{ "first": 1, "second": 2, "third": 3 }}`))

// S is shorthand for Search
children, _ := jsonParsed.S("object").ChildrenMap()  
for key, child := range children {  
    fmt.Printf("key: %v, value: %v\n", key, child.Data().(string))
}

3、遍历数组

核心函数: Children。对于数组,会按顺序返回,对于对象集,返回顺序随机。

...
jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ "first", "second", "third" ]}`))

// S is shorthand for Search
children, _ := jsonParsed.S("array").Children()  
for _, child := range children {  
    fmt.Println(child.Data().(string))
}
...

打印:

first  
second  
third  

4、搜索数组

支持直接搜索对象数据中的值,如下:

jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ {"value":1}, {"value":2}, {"value":3} ]}`))  
fmt.Println(jsonParsed.Path("array.value").String())  

输出:

[1,2,3]

5、生成 JSON

核心函数:NewSet

jsonObj := gabs.New()  
// or gabs.Consume(jsonObject) to work on an existing map[string]interface{}

jsonObj.Set(10, "outter", "inner", "value")  
jsonObj.SetP(20, "outter.inner.value2")  
jsonObj.Set(30, "outter", "inner2", "value3")

fmt.Println(jsonObj.String())  

输出:

{"outter":{"inner":{"value":10,"value2":20},"inner2":{"value3":30}}}

如果要输出的好看(添加缩进),可以如下输出:

fmt.Println(jsonObj.StringIndent("", "  "))  

6、生成数组

核心函数:New, Array, ArrayAppend

jsonObj := gabs.New()

jsonObj.Array("foo", "array")  
// Or .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()

// Create an array with the length of 3
jsonObj.ArrayOfSize(3, "foo")

jsonObj.S("foo").SetIndex("test1", 0)  
jsonObj.S("foo").SetIndex("test2", 1)

// Create an embedded array with the length of 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]]}

7、转换回 JSON

最简单的例子:

jsonParsedObj, _ := gabs.ParseJSON([]byte(`{  
    "outter":{
        "values":{
            "first":10,
            "second":11
        }
    },
    "outter2":"hello world"
}`))

jsonOutput := jsonParsedObj.String()  
// Becomes `{"outter":{"values":{"first":10,"second":11}},"outter2":"hello world"}`

意义何在?比如可以获取子JSON,如下:

jsonOutput := jsonParsedObj.Search("outter").String()  
// Becomes `{"values":{"first":10,"second":11}}`

8、Merge two containers 合并 JSON

支持合并 2 个 JSON 结构到一个,还会自动处理冲突,核心函数 Merge, 如下两个例子:

jsonParsed1, _ := ParseJSON([]byte(`{"outter": {"value1": "one"}}`))  
jsonParsed2, _ := ParseJSON([]byte(`{"outter": {"inner": {"value3": "three"}}, "outter2": {"value2": "two"}}`))

jsonParsed1.Merge(jsonParsed2)  
// Becomes `{"outter":{"inner":{"value3":"three"},"value1":"one"},"outter2":{"value2":"two"}}`
jsonParsed1, _ := ParseJSON([]byte(`{"array": ["one"]}`))  
jsonParsed2, _ := ParseJSON([]byte(`{"array": ["two"]}`))

jsonParsed1.Merge(jsonParsed2)  
// Becomes `{"array":["one", "two"]}`

9、Parsing Numbers

gabs 底层采用的是 Go 标准库中的 json 包,默认会把所有的数字解析为 float64,如果需要解析成 Int,可以使用 json.Decoder,核心函数:ParseJSONDecoder

核心函数:ParseJSONDecoder

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()  
// intValue = 10

参考资料

分享