返回

Go解析JSON:实现结构化解析与自定义属性映射

后端

Go 语言解析 JSON 的多种方式

Go 语言提供了多种解析 JSON 的方法,每种方法都有其特定的优缺点。在本文中,我们将重点介绍两种最常用的方法:使用内置的 encoding/json 包和使用第三方库 jsoniter

使用 encoding/json 包解析 JSON

encoding/json 包是 Go 语言标准库的一部分,提供了解析 JSON 数据的内置功能。它使用简单,但效率可能较低,尤其是在处理大型 JSON 数据时。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	// 定义 JSON 字符串
	jsonStr := `{"name": "John", "age": 30}`

	// 创建一个 Person 类型的变量
	var person Person

	// 使用 json.Unmarshal() 函数将 JSON 字符串解析为 Person 结构体
	err := json.Unmarshal([]byte(jsonStr), &person)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 打印 Person 结构体的字段值
	fmt.Println("Name:", person.Name)
	fmt.Println("Age:", person.Age)
}

使用 jsoniter 库解析 JSON

jsoniter 是一个第三方库,专门用于解析 JSON 数据。它比 encoding/json 包效率更高,并且提供了更多高级特性,如支持非结构化 JSON 数据解析。

package main

import (
	"fmt"

	"github.com/json-iterator/go"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	// 定义 JSON 字符串
	jsonStr := `{"name": "John", "age": 30}`

	// 创建一个 Person 类型的变量
	var person Person

	// 使用 jsoniter.Unmarshal() 函数将 JSON 字符串解析为 Person 结构体
	iter := jsoniter.ParseString(jsonStr)
	err := iter.ToVal(&person)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 打印 Person 结构体的字段值
	fmt.Println("Name:", person.Name)
	fmt.Println("Age:", person.Age)
}

解析 JSON 中的数组

解析 JSON 数组与解析 JSON 对象非常相似。您需要定义一个结构体来表示数组中的元素,然后使用 encoding/json 包或 jsoniter 库中的 Unmarshal() 函数将 JSON 数组解析为结构体数组。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	// 定义 JSON 字符串
	jsonStr := `[
		{"name": "John", "age": 30},
		{"name": "Mary", "age": 25}
	]`

	// 创建一个 Person 类型的数组
	var persons []Person

	// 使用 json.Unmarshal() 函数将 JSON 数组解析为 Person 结构体数组
	err := json.Unmarshal([]byte(jsonStr), &persons)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 遍历 Person 结构体数组并打印每个元素的字段值
	for _, person := range persons {
		fmt.Println("Name:", person.Name)
		fmt.Println("Age:", person.Age)
	}
}

解析 JSON 中的嵌入对象

如果 JSON 数据包含嵌入对象,您可以使用嵌套结构体来表示这些对象。例如,以下 JSON 数据包含了一个嵌套的 Address 对象:

{
  "name": "John",
  "age": 30,
  "address": {
    "street": "123 Main Street",
    "city": "Anytown",
    "state": "CA",
    "zip": "12345"
  }
}

您可以使用以下代码来解析这个 JSON 数据:

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name string
	Age  int
	Address Address
}

type Address struct {
	Street string
	City   string
	State  string
	Zip    string
}

func main() {
	// 定义 JSON 字符串
	jsonStr := `{
		"name": "John",
		"age": 30,
		"address": {
			"street": "123 Main Street",
			"city": "Anytown",
			"state": "CA",
			"zip": "12345"
		}
	}`

	// 创建一个 Person 类型的变量
	var person Person

	// 使用 json.Unmarshal() 函数将 JSON 字符串解析为 Person 结构体
	err := json.Unmarshal([]byte(jsonStr), &person)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 打印 Person 结构体的字段值
	fmt.Println("Name:", person.Name)
	fmt.Println("Age:", person.Age)
	fmt.Println("Address:", person.Address)
}

解析 JSON 中的自定义属性名称

有时,您可能需要将 JSON 数据中的属性名称映射到结构体中的不同名称。这可以通过使用 json:"property_name" 标签来实现。例如,以下代码将 first_name 属性映射到 Name 字段,将 last_name 属性映射到 LastName 字段:

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name string `json:"first_name"`
	LastName string `json:"last_name"`
}

func main() {
	// 定义 JSON 字符串
	jsonStr := `{"first_name": "John", "last_name": "Doe"}`

	// 创建一个 Person 类型的变量
	var person Person

	// 使用 json.Unmarshal() 函数将 JSON 字符串解析为 Person 结构体
	err := json.Unmarshal([]byte(jsonStr), &person)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 打印 Person 结构体的字段值
	fmt.Println("Name:", person.Name)
	fmt.Println("Last Name:", person.LastName)
}

解析非结构化 JSON 字符串

有时,您可能需要解析非结构化的 JSON 字符串,即不是由键值对组成的 JSON 数据。这可以通过使用 json.RawMessage 类型来实现。例如,以下代码将 JSON 字符串解析为 json.RawMessage 类型:

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	// 定义 JSON 字符串
	jsonStr := `["John", "Mary", "Bob"]`

	// 创建一个 json.RawMessage 类型的变量
	var data json.RawMessage

	// 使用 json.Unmarshal() 函数将 JSON 字符串解析为 json.RawMessage 类型
	err := json.Unmarshal([]byte(jsonStr), &data)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 打印 json.RawMessage 类型的变量
	fmt.Println(string(data))
}

结论

Go 语言提供了多种方法来解析 JSON 数据。您可以选择使用内置的 encoding/json 包或第三方库 jsoniter。解析 JSON 数据时,您可以定义结构体来表示 JSON 对象和数组,并使用嵌套结构体来表示嵌入对象。您还可以使用 json:"property_name" 标签来将 JSON 数据中的属性名称映射到结构体中的不同名称。如果您需要解析非结构化的 JSON 字符串,可以使用 json.RawMessage 类型。