📜  golang parse jason (1)

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

Golang Parse JSON

在 Golang 中解析 JSON 数据非常容易,只需要使用内置的 encoding/json 包就可以了。

解析 JSON

让我们从一个简单的例子开始,假设我们有如下的 JSON 数据:

{
  "Name": "John Doe",
  "Age": 30,
  "Email": "john.doe@example.com",
  "Address": {
    "Street": "123 Main St",
    "City": "Anytown",
    "State": "CA",
    "ZipCode": "12345"
  },
  "PhoneNumbers": [
    {
      "Type": "Home",
      "Number": "555-555-1111"
    },
    {
      "Type": "Work",
      "Number": "555-555-2222"
    }
  ]
}

我们可以使用 Unmarshal() 函数将上述 JSON 数据解析成一个 Go 结构体:

type Person struct {
  Name        string
  Age         int
  Email       string
  Address     Address
  PhoneNumbers []PhoneNumber
}

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

type PhoneNumber struct {
  Type    string
  Number  string
}

func main() {
  jsonStr := `
    {
      "Name": "John Doe",
      "Age": 30,
      "Email": "john.doe@example.com",
      "Address": {
        "Street": "123 Main St",
        "City": "Anytown",
        "State": "CA",
        "ZipCode": "12345"
      },
      "PhoneNumbers": [
        {
          "Type": "Home",
          "Number": "555-555-1111"
        },
        {
          "Type": "Work",
          "Number": "555-555-2222"
        }
      ]
    }`

  var person Person
  err := json.Unmarshal([]byte(jsonStr), &person)

  if err != nil {
    fmt.Println(err)
  }

  fmt.Printf("%+v", person)
}

输出结果为:

{Name:"John Doe", Age:30, Email:"john.doe@example.com", Address:{Street:"123 Main St", City:"Anytown", State:"CA", ZipCode:"12345"}, PhoneNumbers:[{Type:"Home", Number:"555-555-1111"}, {Type:"Work", Number:"555-555-2222"}]}
处理错误

当 JSON 数据不符合规范时,例如 JSON 字段中缺少必需的字段或格式错误时,json.Unmarshal() 函数将返回一个错误。

你可以使用 json.Decoder 类型来将 JSON 字段解析为 Token,并使用 Token 类型来访问字段。以下是一个例子:

type Person struct {
  Name        string
  Age         int
  Email       string
  Address     Address
  PhoneNumbers []PhoneNumber
}

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

type PhoneNumber struct {
  Type    string
  Number  string
}

func main() {
  jsonStr := `
    {
      "Name": "John Doe",
      "Age": 30,
      "Address": {
        "City": "Anytown",
        "State": "CA",
        "ZipCode": "12345"
      }
    }`

  var person Person

  decoder := json.NewDecoder(strings.NewReader(jsonStr))
  for {
    token, err := decoder.Token()
    if err == io.EOF {
      break
    }

    if err != nil {
      fmt.Println(err)
    }

    if key, ok := token.(string); ok && key == "Name" {
      decoder.Decode(&person.Name)
    }

    if key, ok := token.(string); ok && key == "Age" {
      decoder.Decode(&person.Age)
    }

    if key, ok := token.(string); ok && key == "Email" {
      decoder.Decode(&person.Email)
    }

    if key, ok := token.(string); ok && key == "Address" {
      decoder.Decode(&person.Address)
    }

    if key, ok := token.(string); ok && key == "PhoneNumbers" {
      decoder.Decode(&person.PhoneNumbers)
    }
  }

  fmt.Printf("%+v", person)
}
输出 JSON

与解析 JSON 数据相反,我们可以使用 Marshal() 函数将结构体转换为 JSON 格式的字符串:

type Person struct {
  Name        string
  Age         int
  Email       string
  Address     Address
  PhoneNumbers []PhoneNumber
}

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

type PhoneNumber struct {
  Type    string
  Number  string
}

func main() {
  person := Person{
    Name: "John Doe",
    Age: 30,
    Email: "john.doe@example.com",
    Address: Address{
      Street: "123 Main St",
      City: "Anytown",
      State: "CA",
      ZipCode: "12345",
    },
    PhoneNumbers: []PhoneNumber{
      {Type: "Home", Number: "555-555-1111"},
      {Type: "Work", Number: "555-555-2222"},
    },
  }

  jsonBytes, err := json.Marshal(person)
  if err != nil {
    fmt.Println(err)
  }

  fmt.Println(string(jsonBytes))
}

输出结果为:

{"Name":"John Doe","Age":30,"Email":"john.doe@example.com","Address":{"Street":"123 Main St","City":"Anytown","State":"CA","ZipCode":"12345"},"PhoneNumbers":[{"Type":"Home","Number":"555-555-1111"},{"Type":"Work","Number":"555-555-2222"}]}
特性处理

在解析或生成 JSON 数据时,encoding/json 包还支持一些有用的特性:

  • 不区分大小写的字段名(在结构体中使用 json:"myField" 可以匹配 JSON 中的 MyFieldmyFieldMYFIELD 等字段名)
  • 使用指针类型的结构体字段(可以在解析 JSON 时将字段设置为 nil,这样就可以检测 JSON 中是否存在该字段)
  • 使用自定义类型实现 json.Unmarshalerjson.Marshaler 接口以支持特定的 JSON 表示形式。
  • 使用标签 json:",omitempty" 相应的字段可以被忽略。
总结

Golang 提供了方便的 JSON 解析和编码功能,使处理 JSON 数据变得简单和直观。同时 encoding/json 包也具有一些有用的特性,可以更方便地处理 JSON 数据。