📜  如何在 Golang 中解析 JSON?(1)

📅  最后修改于: 2023-12-03 15:08:37.309000             🧑  作者: Mango

如何在 Golang 中解析 JSON?

在 Golang 中解析 JSON 可以使用内置的 encoding/json 包,该包提供了 Unmarshal 函数来将 JSON 数据映射到 Golang 中的 struct 类型中。以下是解析 JSON 数据的详细步骤。

1. 定义 JSON 数据结构

首先,需要定义一个 struct 来表示要解析的 JSON 数据结构。例如,如果要解析以下 JSON 数据:

{
  "name": "Alice",
  "age": 30,
  "isMarried": true,
  "hobbies": ["reading", "traveling"]
}

则可以定义如下 struct

type Person struct {
    Name      string
    Age       int
    IsMarried bool
    Hobbies   []string
}

注意,struct 中的字段名需要首字母大写,这样才能被 encoding/json 包识别并解析。

2. 解析 JSON 数据

使用 json.Unmarshal 函数将 JSON 数据解析成 Person 对象。

jsonData := []byte(`{
    "name": "Alice",
    "age": 30,
    "isMarried": true,
    "hobbies": ["reading", "traveling"]
}`)
person := Person{}
err := json.Unmarshal(jsonData, &person)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Name: %s\n", person.Name)
fmt.Printf("Age: %d\n", person.Age)
fmt.Printf("Is married: %t\n", person.IsMarried)
fmt.Printf("Hobbies: %v\n", person.Hobbies)

上述代码中,json.Unmarshal 函数将第一个参数 jsonData 解析成 Person 对象,并将结果存储在第二个参数 &person 中。如果出现错误,则会返回非 nil 的错误值。

3. 处理解析错误

如果 JSON 数据不符合预期,例如包含了未知字段或类型不匹配等错误,json.Unmarshal 函数会返回一个解析错误,需要对错误进行处理。

jsonData := []byte(`{
    "name": "Alice",
    "age": "30", // 这里将 age 字段设为字符串类型
    "isMarried": true,
    "hobbies": ["reading", "traveling"],
    "address": {
        "city": "Shanghai",
        "country": "China"
    }
}`)
person := Person{}
err := json.Unmarshal(jsonData, &person)
if err != nil {
    if e, ok := err.(*json.UnmarshalTypeError); ok {
        log.Printf("Type error: expected %v but got %v", e.Type, e.Value)
    } else if e, ok := err.(*json.InvalidUnmarshalError); ok {
        log.Printf("Invalid unmarshal error: %v", e)
    } else {
        log.Printf("JSON parsing error: %v", err)
    }
}

上述代码中,如果解析错误是类型不匹配,则会输出 "Type error: expected int but got string"。如果 Person 中的某个字段不可导出,则会输出 "Invalid unmarshal error: json: cannot unmarshal object into Go struct field Person.address of type string"。对于其他类型的解析错误,将输出 "JSON parsing error: <error message>"

4. 处理未知字段

有时候,JSON 数据可能包含未知的字段。为了避免出错,需要通过 json.RawMessage 类型来处理这些未知字段。

type Person struct {
    Name      string          `json:"name"`
    Age       int             `json:"age"`
    IsMarried bool            `json:"isMarried"`
    Hobbies   []string        `json:"hobbies"`
    RawFields json.RawMessage `json:"-"`
}

上述代码中,Person 中增加了一个 RawFields 字段,用来存储未知的 JSON 字段。json:",-" 表示该字段不需要进行 JSON 解析映射。

jsonData := []byte(`{
    "name": "Alice",
    "age": 30,
    "isMarried": true,
    "hobbies": ["reading", "traveling"],
    "address": {
        "city": "Shanghai",
        "country": "China"
    }
}`)
person := Person{}
err := json.Unmarshal(jsonData, &person)
if err != nil {
    log.Printf("JSON parsing error: %v", err)
}
fmt.Printf("Name: %s\n", person.Name)
fmt.Printf("Age: %d\n", person.Age)
fmt.Printf("Is married: %t\n", person.IsMarried)
fmt.Printf("Hobbies: %v\n", person.Hobbies)
fmt.Printf("Raw fields: %s\n", string(person.RawFields))

上述代码中,person.RawFields 字段将包含未知的 JSON 字段 "address"

总结

Golang 提供了内置的 encoding/json 包处理 JSON 数据。以创建数据类型映射的方式来解析 JSON 数据,将 JSON 数据解析到 struct 中可以更方便地使用它。错误处理和未知字段处理也是必要的注意点。