encoding/json – Go标准库深度解析

encoding/json – Go标准库深度解析

概述

Go语言的encoding/json包提供了对JSON数据的编码和解码功能。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在现代Web开发和API设计中广泛使用。

核心功能

JSON编码

使用json.Marshal()函数可以将Go数据结构转换为JSON格式:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    p := Person{Name: "Alice", Age: 25}
    jsonData, err := json.Marshal(p)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(jsonData))
    // 输出: {"name":"Alice","age":25}
}

JSON解码

使用json.Unmarshal()函数可以将JSON数据解码为Go数据结构:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    jsonData := []byte(`{"name":"Bob","age":30}`)
    var p Person
    err := json.Unmarshal(jsonData, &p)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("%+v\n", p)
    // 输出: {Name:Bob Age:30}
}

高级特性

自定义编码/解码

通过实现json.Marshalerjson.Unmarshaler接口,可以自定义类型的编码和解码行为:

type CustomDate struct {
    Year  int
    Month int
    Day   int
}

func (d CustomDate) MarshalJSON() ([]byte, error) {
    dateStr := fmt.Sprintf(`"%d-%02d-%02d"`, d.Year, d.Month, d.Day)
    return []byte(dateStr), nil
}

func (d *CustomDate) UnmarshalJSON(data []byte) error {
    var dateStr string
    if err := json.Unmarshal(data, &dateStr); err != nil {
        return err
    }
    parts := strings.Split(dateStr, "-")
    if len(parts) != 3 {
        return fmt.Errorf("invalid date format")
    }
    d.Year, _ = strconv.Atoi(parts[0])
    d.Month, _ = strconv.Atoi(parts[1])
    d.Day, _ = strconv.Atoi(parts[2])
    return nil
}

流式处理

对于大文件或网络流,可以使用json.Encoderjson.Decoder

// 编码到io.Writer
func encodeToWriter(w io.Writer, data interface{}) error {
    enc := json.NewEncoder(w)
    return enc.Encode(data)
}

// 从io.Reader解码
func decodeFromReader(r io.Reader, v interface{}) error {
    dec := json.NewDecoder(r)
    return dec.Decode(v)
}

处理未知字段

使用json.RawMessage可以延迟解码部分JSON数据:

type Message struct {
    Type    string          `json:"type"`
    Payload json.RawMessage `json:"payload"`
}

var m Message
json.Unmarshal(data, &m)
// 根据m.Type决定如何解析m.Payload

性能考虑

  1. 复用Encoder/Decoder:在频繁操作时,复用这些对象可以减少内存分配
  2. 预分配slice/map:对于大数组或对象,预分配空间可以提高性能
  3. 使用字节切片:避免不必要的string转换

常见错误处理

JSON标签使用

type Example struct {
    Field1 string `json:"field1"`           // JSON key为"field1"
    Field2 string `json:"field2,omitempty"` // 如果为空则忽略此字段
    Field3 string `json:"-"`                // 忽略此字段
}

处理特殊值

JSON没有NaNInf等特殊数值,处理时需要特别小心:

func (f Float64) MarshalJSON() ([]byte, error) {
    if math.IsNaN(float64(f)) {
        return []byte(`"NaN"`), nil
    }
    return json.Marshal(float64(f))
}

实战建议

  1. 总是检查MarshalUnmarshal的错误
  2. 对于API响应,考虑使用自定义错误类型
  3. 在生产环境中,建议限制解码的最大深度和大小以防恶意输入

总结

encoding/json包是Go语言处理JSON数据的标准方式,它提供了从简单到复杂的全方位处理能力。掌握这个包对于任何Go开发者来说都是必不可少的技能。

预告:下一期我们将深入研究net/http包,它是Go语言构建Web服务的核心工具。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇