encoding/json:Go语言中的JSON编码与解码

encoding/json:Go语言中的JSON编码与解码

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,因其易于阅读和编写的特性,在现代网络应用中广泛使用。Go语言的标准库encoding/json提供了完整的JSON编码和解码功能,支持Go数据结构和JSON数据之间的相互转换。

基本使用

JSON编码(Marshal)

将Go数据结构转换为JSON字符串的过程称为”编码”或”序列化”,在encoding/json包中通过Marshal函数实现:

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}

    data, err := json.Marshal(p)
    if err != nil {
        fmt.Println("JSON编码错误:", err)
        return
    }

    fmt.Println(string(data)) // 输出: {"name":"Alice","age":25}
}

JSON解码(Unmarshal)

将JSON字符串解析为Go数据结构的过程称为”解码”或”反序列化”,通过Unmarshal函数实现:

func main() {
    jsonData := `{"name":"Bob","age":30}`

    var p Person
    err := json.Unmarshal([]byte(jsonData), &p)
    if err != nil {
        fmt.Println("JSON解码错误:", err)
        return
    }

    fmt.Printf("%+v\n", p) // 输出: {Name:Bob Age:30}
}

高级特性

结构体标签

结构体字段的标签可以控制编码过程中的JSON字段名:

type User struct {
    Username string `json:"user_name"`
    Password string `json:"-"`            // 忽略该字段
    Email    string `json:"email,omitempty"` // 如果为空则忽略
}
  • json:"user_name":指定JSON字段名为”user_name”
  • json:"-":完全忽略该字段
  • json:"email,omitempty":如果email为空则不在JSON中输出该字段

编解码器

对于流式数据或需要更细致控制的情况,可以使用json.Encoderjson.Decoder

func streamExample() {
    // 编码器示例
    data := Person{Name: "Charlie", Age: 35}
    enc := json.NewEncoder(os.Stdout)
    enc.Encode(data)  // 直接输出到标准输出

    // 解码器示例
    input := `{"name":"Dave","age":40}`
    dec := json.NewDecoder(strings.NewReader(input))
    var p Person
    dec.Decode(&p)
    fmt.Printf("%+v\n", p)
}

处理动态JSON

处理未知结构的JSON数据时,可以使用map[string]interface{}json.RawMessage

func handleDynamicJSON() {
    data := `{"name":"Eve","age":45,"hobbies":["reading","swimming"]}`

    var result map[string]interface{}
    json.Unmarshal([]byte(data), &result)

    age := result["age"].(float64) // JSON数字默认转为float64
    fmt.Println(age)

    hobbies := result["hobbies"].([]interface{})
    for _, h := range hobbies {
        fmt.Println(h.(string))
    }
}

性能优化

复用解码器

var decoderPool = sync.Pool{
    New: func() interface{} {
        return json.NewDecoder(nil)
    },
}

func decodeWithPool(data []byte, v interface{}) error {
    dec := decoderPool.Get().(*json.Decoder)
    defer decoderPool.Put(dec)

    dec.Reset(bytes.NewReader(data))
    return dec.Decode(v)
}

使用jsoniter

虽然jsoniter不是标准库的一部分,但它提供了更快的JSON处理速度:

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

var jsonIter = jsoniter.ConfigCompatibleWithStandardLibrary

func useJsonIter() {
    data, _ := jsonIter.Marshal(&Person{Name: "Frank", Age: 50})

    var p Person
    jsonIter.Unmarshal(data, &p)
}

常见问题

  1. 字段可见性问题:只有首字母大写的字段才会被编码/解码
  2. 零值处理:数字0、空字符串等在JSON中会被编码
  3. 自定义编解码:通过实现json.Marshalerjson.Unmarshaler接口可以自定义编解码行为
type CustomTime time.Time

func (ct *CustomTime) UnmarshalJSON(data []byte) error {
    // 自定义时间解析逻辑
}

func (ct CustomTime) MarshalJSON() ([]byte, error) {
    // 自定义时间格式化为JSON
}

总结

encoding/json包提供了Go语言与JSON数据交互的完整功能集。通过掌握基本编码解码、结构体标签、流式处理和动态JSON等特性,可以高效地在Go程序中处理JSON数据。对于性能敏感的场景,可以考虑使用对象池或替代实现如jsoniter。

文末预告:下一期我们将深入学习net/http包——Go语言中构建HTTP服务与客户端的核心工具。

暂无评论

发送评论 编辑评论


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