找回密码
 立即注册
查看: 440|回复: 0

[后端] Go语言如何处理 JSON 中的 `null` 值?

[复制链接]

279

主题

0

回帖

964

积分

超级版主

积分
964
发表于 2024-5-20 12:11:30 | 显示全部楼层 |阅读模式
本帖最后由 Shaw0xyz 于 2024-5-20 12:12 编辑

在处理 JSON 数据时,我们经常会遇到 `null` 值。与其他一些语言不同, 语言没有直接的联合类型(Union Type)来处理多种类型的数据。那么, 是如何优雅地处理 JSON 中的 `null` 值的呢?本文将为你详细解析。

一、JSON 中的 `null` 值

在 JSON 中,`null` 表示一个值不存在或为空。下面是一个包含 `null` 值的 JSON 示例:

  1. {
  2.     "name": "Alice",
  3.     "age": null,
  4.     "Email": "[email protected]"
  5. }
复制代码


对于这种情况,我们希望在反序列化(unmarshal)到  结构体时,能够正确处理 `null` 值。

二、 语言中的解决方案

语言没有联合类型,但通过以下几种方式,我们可以有效地处理 JSON 中的 `null` 值:

1. 使用指针

最常见的方式是使用指针类型。通过指针,可以区分字段是否在 JSON 中存在或被显式设置为 `null`。

  1. package main

  2. import (
  3.     "encoding/json"
  4.     "fmt"
  5. )

  6. type Person struct {
  7.     Name  string  `json:"name"`
  8.     Age   *int    `json:"age"`
  9.     Email string  `json:"email"`
  10. }

  11. func main() {
  12.     jsonData := `{"name": "Alice", "age": null, "email": "[email protected]"}`
  13.     var person Person
  14.     err := json.Unmarshal([]byte(jsonData), &person)
  15.     if err != nil {
  16.         fmt.Println("Error unmarshalling JSON:", err)
  17.         return
  18.     }
  19.     fmt.Printf("Name: %s\n", person.Name)
  20.     if person.Age == nil {
  21.         fmt.Println("Age: null")
  22.     } else {
  23.         fmt.Printf("Age: %d\n", *person.Age)
  24.     }
  25.     fmt.Printf("Email: %s\n", person.Email)
  26. }
复制代码


在这个例子中,`Age` 字段使用了 `*int` 类型。通过检查 `Age` 是否为 `nil`,我们可以判断原始 JSON 中该字段是否为 `null`。

2. 使用 `sql.NullXXX`

标准库中的 `database/sql` 包提供了一些辅助类型,如 `sql.NullInt64`、`sql.NullString` 等,用于处理数据库中的 `null` 值。我们可以借助这些类型来处理 JSON 中的 `null`。

  1. package main

  2. import (
  3.     "database/sql"
  4.     "encoding/json"
  5.     "fmt"
  6. )

  7. type Person struct {
  8.     Name  string       `json:"name"`
  9.     Age   sql.NullInt64 `json:"age"`
  10.     Email string       `json:"email"`
  11. }

  12. func main() {
  13.     jsonData := `{"name": "Alice", "age": null, "email": "[email protected]"}`
  14.     var person Person
  15.     err := json.Unmarshal([]byte(jsonData), &person)
  16.     if err != nil {
  17.         fmt.Println("Error unmarshalling JSON:", err)
  18.         return
  19.     }
  20.     fmt.Printf("Name: %s\n", person.Name)
  21.     if !person.Age.Valid {
  22.         fmt.Println("Age: null")
  23.     } else {
  24.         fmt.Printf("Age: %d\n", person.Age.Int64)
  25.     }
  26.     fmt.Printf("Email: %s\n", person.Email)
  27. }
复制代码

在这个例子中,`Age` 使用了 `sql.NullInt64` 类型,通过检查其 `Valid` 字段来判断是否为 `null`。

3. 自定义类型和 `UnmarshalJSON` 方法

我们还可以定义自定义类型,并实现 `json.Unmarshaler` 接口,以更灵活地处理 JSON 中的 `null` 值。

  1. package main

  2. import (
  3.     "encoding/json"
  4.     "fmt"
  5. )

  6. type NullInt struct {
  7.     Value int
  8.     Valid bool
  9. }

  10. func (ni *NullInt) UnmarshalJSON(data []byte) error {
  11.     if string(data) == "null" {
  12.         ni.Valid = false
  13.         return nil
  14.     }
  15.     if err := json.Unmarshal(data, &ni.Value); err != nil {
  16.         return err
  17.     }
  18.     ni.Valid = true
  19.     return nil
  20. }

  21. type Person struct {
  22.     Name  string   `json:"name"`
  23.     Age   NullInt  `json:"age"`
  24.     Email string   `json:"email"`
  25. }

  26. func main() {
  27.     jsonData := `{"name": "Alice", "age": null, "email": "[email protected]"}`
  28.     var person Person
  29.     err := json.Unmarshal([]byte(jsonData), &person)
  30.     if err != nil {
  31.         fmt.Println("Error unmarshalling JSON:", err)
  32.         return
  33.     }
  34.     fmt.Printf("Name: %s\n", person.Name)
  35.     if !person.Age.Valid {
  36.         fmt.Println("Age: null")
  37.     } else {
  38.         fmt.Printf("Age: %d\n", person.Age.Value)
  39.     }
  40.     fmt.Printf("Email: %s\n", person.Email)
  41. }
复制代码

在这个例子中,我们定义了一个 `NullInt` 类型,并实现了 `UnmarshalJSON` 方法,通过解析 JSON 数据判断值是否为 `null`。

三、总结

语言虽然没有联合类型,但通过使用指针、`sql.NullXXX` 类型和自定义类型,可以有效地处理 JSON 中的 `null` 值。这些方法各有优缺点:

1. 指针:简单易用,但会增加对指针的处理逻辑。
2. `sql.NullXXX`:标准库支持,适合与数据库结合使用,但略显冗长。
3. 自定义类型:灵活性最高,可以根据需求定制,但需要额外的代码实现。

选择合适的方法处理 JSON 中的 `null` 值,可以让你的  代码更加健壮和可靠。希望这篇文章能帮助你更好地理解和处理  语言中的 JSON `null` 值问题。Happy coding with !

荔枝学姐爱吃荔枝!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

联系站长|Archiver|手机版|小黑屋|主机论坛

GMT+8, 2025-4-4 13:56 , Processed in 0.062868 second(s), 24 queries .

Powered by 主机论坛 HostSsss.Com

HostSsss.Com

快速回复 返回顶部 返回列表