Go 语言 json解析框架与 gjson 详解

介绍

在 Golang 中,解析 JSON 数据是一项非常常见的任务。Go提供了标准的JSON包,可以轻松地将JSON数据编组和解组。但是,在使用标准JSON包解析大型复杂JSON结构时,可能存在些许不足,例如代码冗余,性能瓶颈等问题。针对这些问题,目前有许多优秀的JSON解析框架,GJSON是其中一个很不错的选择。本文将详细讲解如何使用GJSON框架解析JSON数据。

安装

GJSON模块可以通过go get命令来安装。

go get github.com/tidwall/gjson

示例1 – JSON数据解析

我们可以通过一段简单的JSON数据来展示GJSON的具体使用方法。

{
    "name": {
        "first": "Tom",
        "last": "Jerry"
    },
    "age": 20,
    "hobbies": [
        "sport",
        "music",
        "reading"
    ]
}

获取简单的值

我们可以使用gjson.Get函数访问JSON数据的属性。下面是一些例子:

package main

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

func main() {
    jsonData := `{"name": {"first": "Tom", "last": "Jerry"}, "age": 20, "hobbies":["sport","music","reading"]}`

    name := gjson.Get(jsonData, "name")
    first := gjson.Get(jsonData, "name.first")
    last := gjson.Get(jsonData, "name.last")
    age := gjson.Get(jsonData, "age")
    hobbies := gjson.Get(jsonData, "hobbies")

    fmt.Println("Name:", name)
    fmt.Println("First:", first)
    fmt.Println("Last:", last)
    fmt.Println("Age:", age)
    fmt.Println("Hobbies:", hobbies)
}

输出结果:

Name: {"first":"Tom","last":"Jerry"}
First: Tom
Last: Jerry
Age: 20
Hobbies: ["sport","music","reading"]

访问复杂的属性

GJSON提供了一个具有强大的语法来访问JSON任意节点。我们可以使用.(点)或.[](点括号)来访问节点。下面例子分别演示了访问数组、普通节点、以及数组节点中的一项元素。

package main

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

func main() {
    jsonData := `{"name": {"first": "Tom", "last": "Jerry"}, "age": 20, "hobbies":["sport","music","reading"]}`

    hobby1 := gjson.Get(jsonData, "hobbies.0")
    allHubbies := gjson.Get(jsonData, "hobbies")
    firstName := gjson.Get(jsonData, "name.first")
    nameString := gjson.Get(jsonData, "name.first") + " " + gjson.Get(jsonData, "name.last")

    fmt.Println("Hobby1:", hobby1)
    fmt.Println("All Hubbies:", allHubbies)
    fmt.Println("First Name:", firstName)
    fmt.Println("Name String:", nameString)
}

输出结果:

Hobby1: sport
All Hubbies: ["sport","music","reading"]
First Name: Tom
Name String: Tom Jerry

访问非字符串值

当你的JSON数据包含非字符串值时,你可以使用各种类型的JSON类型进行解析。下面是一些可用类型:

方法 描述
Bool() 尝试将此值转换为布尔型。
Float64() 尝试将此值转换为float64。
Int() 尝试将此值转换为int64。
Uint64() 尝试将此值转换为uint64。
String() 获取字符串版本(或数字,布尔值等)。

下面是一个使用不同类型的例子:

package main

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

func main() {
    jsonData := `{"value": "42", "price": 3.14, "isValid": true}`

    valueStr := gjson.Get(jsonData, "value").String()
    valueNum := gjson.Get(jsonData, "value").Int()
    priceNum := gjson.Get(jsonData, "price").Float()
    isValid := gjson.Get(jsonData, "isValid").Bool()

    fmt.Printf("Value Str: %s\n", valueStr)
    fmt.Printf("Value Num: %d\n", valueNum)
    fmt.Printf("Price Num: %.2f\n", priceNum)
    fmt.Printf("Is Valid: %t\n", isValid)
}

输出结果:

Value Str: 42
Value Num: 42
Price Num: 3.14
Is Valid: true

示例2 – JSON数据迭代器

gjson.ForEach
{
  "result": [
    {
      "name": "Tom",
      "age": 30,
      "items": [
        {
          "id": 1,
          "name": "Book"
        },
        {
          "id": 2,
          "name": "Bike"
        }
      ]
    },
    {
      "name": "Jerry",
      "age": 20,
      "items": [
        {
          "id": 3,
          "name": "Computer"
        }
      ]
    }
  ]
}
package main

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

func main() {
    jsonData := `{
  "result": [
    {
      "name": "Tom",
      "age": 30,
      "items": [
        {
          "id": 1,
          "name": "Book"
        },
        {
          "id": 2,
          "name": "Bike"
        }
      ]
    },
    {
      "name": "Jerry",
      "age": 20,
      "items": [
        {
          "id": 3,
          "name": "Computer"
        }
      ]
    }
  ]
}`

    gjson.Get(jsonData, "result").ForEach(func(key, value gjson.Result) bool {

        name := value.Get("name").String()
        age := value.Get("age").Int()

        fmt.Printf("Name: %s, age: %d\n", name, age)

        value.Get("items").ForEach(func(key, itemValue gjson.Result) bool {
            itemName := itemValue.Get("name").String()
            itemID := itemValue.Get("id").Int()

            fmt.Printf("    Item %s, id: %d\n", itemName, itemID)

            return true
        })

        return true
    })
}

输出结果:

Name: Tom, age: 30
    Item Book, id: 1
    Item Bike, id: 2
Name: Jerry, age: 20
    Item Computer, id: 3