Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

encoding/json - JSON 编解码

概述

encoding/json 包提供了 JSON(JavaScript Object Notation)数据的编码和解码功能。

JSON 是什么

  • 📦 轻量级数据格式:基于 JavaScript 的对象表示法
  • 🔧 通用数据交换:Web API、配置文件、数据存储的标准格式
  • 📋 人类可读:文本格式,易于阅读和编写
  • 🛠️ 跨语言支持:几乎所有编程语言都支持 JSON

主要用途

  • 🌐 Web API:RESTful API 的请求和响应数据
  • 📧 配置文件:应用程序配置存储
  • 🔐 数据传输:客户端与服务器之间的数据交换
  • 📊 数据存储:NoSQL 数据库(如 MongoDB)的文档格式
  • 🖼️ 序列化:对象的状态持久化
  • 🔑 日志记录:结构化日志输出

重要说明

  • ⚠️ UTF-8 编码:JSON 默认使用 UTF-8 字符编码
  • ⚠️ 字段可见性:只导出大写字段(导出字段)
  • ⚠️ 标签语法:使用 struct tag 自定义字段名和选项
  • ⚠️ 类型映射:Go 类型与 JSON 类型的映射关系
  • 标准库支持:Go 标准库提供完整支持
  • 流式处理:支持 Encoder/Decoder 流式编解码
  • 自定义编解码:实现 Marshaler/Unmarshaler 接口

JSON 示例

{
  "name": "John Doe",
  "age": 30,
  "email": "john@example.com",
  "active": true,
  "tags": ["developer", "golang"],
  "address": {
    "city": "New York",
    "zip": "10001"
  }
}

JSON 基础

JSON 数据类型

6 种基本类型

  1. 对象(Object):{} - 键值对集合
  2. 数组(Array):[] - 有序值列表
  3. 字符串(String):"" - 双引号包围的文本
  4. 数字(Number):整数或浮点数
  5. 布尔值(Boolean):truefalse
  6. 空值(Null):null

示例

{
  "string": "hello",
  "number": 42,
  "float": 3.14,
  "boolean": true,
  "null": null,
  "array": [1, 2, 3],
  "object": {"key": "value"}
}

Go 与 JSON 类型映射

Go 类型JSON 类型说明
boolbooleantrue/false
int, int8-64number整数
uint, uint8-64number无符号整数
float32, float64number浮点数
stringstring字符串
[]Tarray切片
[N]Tarray数组
structobject结构体
map[string]Tobject映射
pointerobject/array/etc指针(解引用)
interface{}any任意类型
nilnull空值
time.TimestringISO 8601 格式
[]bytestringBase64 编码

核心函数

1. Marshal - 编码为 JSON

func Marshal(v interface{}) ([]byte, error)

功能:将 Go 值编码为 JSON 字节切片。

编码规则

  • 结构体字段必须大写(导出)
  • 默认使用字段名作为 JSON 键
  • 可使用 struct tag 自定义
  • 忽略值为零值的字段(使用 omitempty
  • 指针会被解引用
  • nil 指针或接口编码为 null

示例

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

user := User{Name: "John", Age: 30}
data, err := json.Marshal(user)
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(data))
// 输出:{"name":"John","age":30}

2. MarshalIndent - 格式化编码

func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)

功能:将 Go 值编码为格式化的 JSON(带缩进)。

参数

  • v:要编码的值
  • prefix:每行前缀(通常为空字符串)
  • indent:缩进字符串(通常为空格或制表符)

示例

data, err := json.MarshalIndent(user, "", "  ")
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(data))
/*
输出:
{
  "name": "John",
  "age": 30
}
*/

3. Unmarshal - 从 JSON 解码

func Unmarshal(data []byte, v interface{}) error

功能:将 JSON 数据解码到 Go 值。

参数

  • data:JSON 字节切片
  • v:指向目标变量的指针

解码规则

  • JSON 对象解码到结构体或 map
  • JSON 数组解码到切片或数组
  • JSON 数字默认解码为 float64
  • 字段名匹配不区分大小写
  • 未匹配的 JSON 字段被忽略
  • 未初始化的 Go 字段保持零值

示例

var user User
err := json.Unmarshal(data, &user)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("%+v\n", user)

4. Valid - 验证 JSON

func Valid(data []byte) bool

功能:检查 JSON 数据是否有效。

示例

if json.Valid(data) {
    fmt.Println("有效的 JSON")
} else {
    fmt.Println("无效的 JSON")
}

5. HTMLEscape - HTML 转义

func HTMLEscape(dst *bytes.Buffer, src []byte)

功能:将 JSON 中的 HTML 特殊字符转义。

转义字符

  • &\u0026
  • <\u003c
  • >\u003e

示例

data := []byte(`{"html": "<script>alert(1)</script>"}`)
var buf bytes.Buffer
json.HTMLEscape(&buf, data)
fmt.Println(buf.String())
// 输出:{"html": "\u003cscript\u003ealert(1)\u003c/script\u003e"}

核心类型

1. Encoder - JSON 编码器

type Encoder struct {
    // 包含过滤或未导出的字段
}

功能:将 Go 值流式编码到 io.Writer。

创建方法

func NewEncoder(w io.Writer) *Encoder

主要方法

// 编码单个值
func (enc *Encoder) Encode(v interface{}) error

// 设置缩进
func (enc *Encoder) SetIndent(prefix, indent string)

// 设置 HTML 转义
func (enc *Encoder) SetEscapeHTML(on bool)

使用示例

encoder := json.NewEncoder(os.Stdout)
err := encoder.Encode(user)
if err != nil {
    log.Fatal(err)
}

2. Decoder - JSON 解码器

type Decoder struct {
    // 包含过滤或未导出的字段
}

功能:从 io.Reader 流式解码 JSON。

创建方法

func NewDecoder(r io.Reader) *Decoder

主要方法

// 解码单个值
func (dec *Decoder) Decode(v interface{}) error

// 获取解码器中的下一个 token
func (dec *Decoder) Token() (Token, error)

// 检查是否还有更多数据
func (dec *Decoder) More() bool

// 返回解码器中的下一个 JSON 值
func (dec *Decoder) InputOffset() int64

// 使用指定类型存储下一个 JSON 值
func (dec *Decoder) UseNumber()

使用示例

decoder := json.NewDecoder(reader)
var user User
err := decoder.Decode(&user)
if err != nil {
    log.Fatal(err)
}

3. RawMessage - 原始 JSON

type RawMessage []byte

功能:存储原始 JSON 数据,延迟解码。

用途

  • 延迟解码(先存储,后解码)
  • 解码未知结构的数据
  • 部分解码(部分字段延迟处理)

示例

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

var event Event
json.Unmarshal(data, &event)

// 根据类型解码 payload
var payload map[string]interface{}
json.Unmarshal(event.Payload, &payload)

4. Number - JSON 数字

type Number string

功能:表示 JSON 数字,保持精度。

用途

  • 避免浮点数精度丢失
  • 处理大整数(超过 int64 范围)
  • 保持原始数字格式

方法

// 转换为 float64
func (n Number) Float64() (float64, error)

// 转换为 int64
func (n Number) Int64() (int64, error)

// 转换为 string
func (n Number) String() string

使用示例

// 使用 UseNumber() 保持精度
decoder := json.NewDecoder(reader)
decoder.UseNumber()

var data map[string]interface{}
decoder.Decode(&data)

num := data["large_number"].(json.Number)
intVal, _ := num.Int64()

5. Token - JSON Token

type Token interface{}

功能:表示 JSON 对象或数组的边界标记。

特殊值

  • Delim('{'):对象开始
  • Delim('}'):对象结束
  • Delim('['):数组开始
  • Delim(']'):数组结束

示例

decoder := json.NewDecoder(reader)
for {
    token, err := decoder.Token()
    if err == io.EOF {
        break
    }
    fmt.Printf("Token: %v\n", token)
}

Struct Tag 详解

基本语法

type Struct struct {
    Field  Type  `json:"key,options"`
}

常用选项

选项说明示例
字段名自定义 JSON 键名json:"name"
omitempty零值时忽略json:"name,omitempty"
string数字编码为字符串json:"age,string"
-“忽略字段json:"-"

字段名自定义

type User struct {
    Name     string `json:"username"`      // 自定义键名
    Email    string `json:"email_address"` // 下划线命名
    Password string `json:"-"`             // 忽略此字段
}

omitempty 选项

零值定义

  • 0(数字类型)
  • ""(空字符串)
  • nil(指针、切片、映射、接口)
  • false(布尔)
  • 空结构体
type Product struct {
    ID          int      `json:"id"`
    Name        string   `json:"name,omitempty"`
    Description string   `json:"description,omitempty"`
    Price       float64  `json:"price,omitempty"`
    Tags        []string `json:"tags,omitempty"`
}

// 如果 Name 为空字符串,则不会出现在 JSON 中

string 选项

用途:将数字编码为字符串(或从字符串解码数字)。

type Config struct {
    Port     int    `json:"port,string"`      // "8080" ↔ 8080
    Timeout  int64  `json:"timeout,string"`   // "30" ↔ 30
    Enabled  bool   `json:"enabled,string"`   // "true" ↔ true
}

组合选项

type Data struct {
    ID    int    `json:"id,omitempty"`
    Name  string `json:"name,omitempty"`
    Count int    `json:"count,string,omitempty"`
}

完整示例

示例 1:基本编解码

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

// User 用户结构
type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
    Age   int    `json:"age"`
}

func main() {
    fmt.Println("=== JSON 基本编解码 ===\n")
    
    // 1. 创建数据
    user := User{
        ID:    1,
        Name:  "John Doe",
        Email: "john@example.com",
        Age:   30,
    }
    
    fmt.Printf("原始数据:\n")
    fmt.Printf("  ID: %d\n", user.ID)
    fmt.Printf("  Name: %s\n", user.Name)
    fmt.Printf("  Email: %s\n", user.Email)
    fmt.Printf("  Age: %d\n\n", user.Age)
    
    // 2. 编码为 JSON
    fmt.Println("2. 编码为 JSON:")
    data, err := json.Marshal(user)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("  紧凑格式:%s\n", string(data))
    
    // 格式化输出
    indentData, err := json.MarshalIndent(user, "", "  ")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("\n  格式化格式:\n%s\n\n", string(indentData))
    
    // 3. 从 JSON 解码
    fmt.Println("3. 从 JSON 解码:")
    var decoded User
    err = json.Unmarshal(data, &decoded)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("  解码结果:\n")
    fmt.Printf("  ID: %d\n", decoded.ID)
    fmt.Printf("  Name: %s\n", decoded.Name)
    fmt.Printf("  Email: %s\n", decoded.Email)
    fmt.Printf("  Age: %d\n\n", decoded.Age)
    
    // 4. 验证
    fmt.Printf("验证:%v\n", user == decoded)
    
    // 5. 验证 JSON 有效性
    fmt.Printf("JSON 有效性:%v\n", json.Valid(data))
}

输出

=== JSON 基本编解码 ===

原始数据:
  ID: 1
  Name: John Doe
  Email: john@example.com
  Age: 30

2. 编码为 JSON:
  紧凑格式:{"id":1,"name":"John Doe","email":"john@example.com","age":30}

  格式化格式:
{
  "id": 1,
  "name": "John Doe",
  "email": "john@example.com",
  "age": 30
}

3. 从 JSON 解码:
  解码结果:
  ID: 1
  Name: John Doe
  Email: john@example.com
  Age: 30

验证:true
JSON 有效性:true

示例 2:Struct Tag 使用

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

// Product 产品(使用各种 struct tag)
type Product struct {
    ID          int      `json:"id"`
    Name        string   `json:"name"`
    Description string   `json:"description,omitempty"`
    Price       float64  `json:"price"`
    Category    string   `json:"category,omitempty"`
    Tags        []string `json:"tags,omitempty"`
    InternalID  int      `json:"-"`  // 完全忽略
    secret      string   // 未导出,自动忽略
}

// Config 配置(使用 string 选项)
type Config struct {
    Port     int    `json:"port,string"`
    Host     string `json:"host"`
    Timeout  int64  `json:"timeout,string"`
    Debug    bool   `json:"debug,string"`
}

func main() {
    fmt.Println("=== Struct Tag 使用 ===\n")
    
    // 1. omitempty 测试
    fmt.Println("1. omitempty 测试:")
    
    product1 := Product{
        ID:         1,
        Name:       "Laptop",
        Description: "High performance laptop",
        Price:      999.99,
        Category:   "Electronics",
        Tags:       []string{"computer", "portable"},
        InternalID: 12345,
        secret:     "secret",
    }
    
    data1, _ := json.MarshalIndent(product1, "", "  ")
    fmt.Printf("完整产品:\n%s\n\n", string(data1))
    
    // 空字段测试
    product2 := Product{
        ID:    2,
        Name:  "Mouse",
        Price: 29.99,
        // Description, Category, Tags 为空
    }
    
    data2, _ := json.MarshalIndent(product2, "", "  ")
    fmt.Printf("省略空字段:\n%s\n\n", string(data2))
    
    // 2. string 选项测试
    fmt.Println("2. string 选项测试:")
    
    config := Config{
        Port:    8080,
        Host:    "localhost",
        Timeout: 30,
        Debug:   true,
    }
    
    data3, err := json.MarshalIndent(config, "", "  ")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("编码配置:\n%s\n\n", string(data3))
    
    // 3. 解码 string 选项
    fmt.Println("3. 解码 string 选项:")
    
    jsonStr := `{
        "port": "9090",
        "host": "example.com",
        "timeout": "60",
        "debug": "false"
    }`
    
    var decodedConfig Config
    err = json.Unmarshal([]byte(jsonStr), &decodedConfig)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("解码配置:\n")
    fmt.Printf("  Port: %d (类型:%T)\n", decodedConfig.Port, decodedConfig.Port)
    fmt.Printf("  Host: %s\n", decodedConfig.Host)
    fmt.Printf("  Timeout: %d\n", decodedConfig.Timeout)
    fmt.Printf("  Debug: %v\n\n", decodedConfig.Debug)
    
    // 4. 字段名映射
    fmt.Println("4. 字段名映射:")
    
    jsonCustom := `{
        "id": 3,
        "name": "Keyboard",
        "description": "Mechanical keyboard",
        "price": 79.99,
        "category": "Peripherals",
        "tags": ["input", "gaming"]
    }`
    
    var product3 Product
    err = json.Unmarshal([]byte(jsonCustom), &product3)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("解码产品:\n")
    fmt.Printf("  ID: %d\n", product3.ID)
    fmt.Printf("  Name: %s\n", product3.Name)
    fmt.Printf("  Description: %s\n", product3.Description)
    fmt.Printf("  Price: %.2f\n", product3.Price)
    fmt.Printf("  Category: %s\n", product3.Category)
    fmt.Printf("  Tags: %v\n", product3.Tags)
    fmt.Printf("  InternalID: %d (未出现在 JSON 中)\n", product3.InternalID)
}

输出

=== Struct Tag 使用 ===

1. omitempty 测试:
完整产品:
{
  "id": 1,
  "name": "Laptop",
  "description": "High performance laptop",
  "price": 999.99,
  "category": "Electronics",
  "tags": [
    "computer",
    "portable"
  ]
}

省略空字段:
{
  "id": 2,
  "name": "Mouse",
  "price": 29.99
}

2. string 选项测试:
编码配置:
{
  "port": "8080",
  "host": "localhost",
  "timeout": "30",
  "debug": "true"
}

3. 解码 string 选项:
解码配置:
  Port: 9090 (类型:int)
  Host: example.com
  Timeout: 60
  Debug: false

4. 字段名映射:
解码产品:
  ID: 3
  Name: Keyboard
  Description: Mechanical keyboard
  Price: 79.99
  Category: Peripherals
  Tags: [input gaming]
  InternalID: 12345 (未出现在 JSON 中)

示例 3:复杂数据结构

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "time"
)

// Address 地址
type Address struct {
    Street  string `json:"street"`
    City    string `json:"city"`
    State   string `json:"state"`
    ZipCode string `json:"zip_code"`
    Country string `json:"country"`
}

// Contact 联系方式
type Contact struct {
    Type  string `json:"type"`
    Value string `json:"value"`
}

// User 用户(嵌套结构)
type User struct {
    ID        int       `json:"id"`
    Username  string    `json:"username"`
    Email     string    `json:"email"`
    CreatedAt time.Time `json:"created_at"`
    Address   Address   `json:"address"`
    Contacts  []Contact `json:"contacts"`
    Metadata  map[string]interface{} `json:"metadata"`
}

// Company 公司
type Company struct {
    Name      string   `json:"name"`
    Founded   int      `json:"founded"`
    Employees int      `json:"employees"`
    Departments []string `json:"departments"`
    CEO       *User    `json:"ceo"`  // 指针
    Offices   []Address `json:"offices"`
}

func main() {
    fmt.Println("=== 复杂数据结构 ===\n")
    
    // 1. 创建嵌套数据
    user := User{
        ID:       1,
        Username: "john_doe",
        Email:    "john@example.com",
        CreatedAt: time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC),
        Address: Address{
            Street:  "123 Main St",
            City:    "New York",
            State:   "NY",
            ZipCode: "10001",
            Country: "USA",
        },
        Contacts: []Contact{
            {Type: "phone", Value: "+1-555-1234"},
            {Type: "email", Value: "john.doe@example.com"},
        },
        Metadata: map[string]interface{}{
            "age":     30,
            "married": true,
            "hobbies": []string{"reading", "coding"},
        },
    }
    
    // 2. 编码
    fmt.Println("2. 编码嵌套结构:")
    data, err := json.MarshalIndent(user, "", "  ")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("%s\n\n", string(data))
    
    // 3. 解码
    fmt.Println("3. 解码嵌套结构:")
    var decoded User
    err = json.Unmarshal(data, &decoded)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("解码用户:\n")
    fmt.Printf("  用户名:%s\n", decoded.Username)
    fmt.Printf("  城市:%s\n", decoded.Address.City)
    fmt.Printf("  联系方式:%d 个\n", len(decoded.Contacts))
    fmt.Printf("  元数据年龄:%v\n", decoded.Metadata["age"])
    
    // 4. 公司结构(包含指针)
    fmt.Println("\n4. 公司结构:")
    
    company := Company{
        Name:      "TechCorp",
        Founded:   2010,
        Employees: 500,
        Departments: []string{"Engineering", "Sales", "Marketing"},
        CEO:       &user,  // 指向之前的 user
        Offices: []Address{
            {Street: "1 Tech Plaza", City: "San Francisco", State: "CA", ZipCode: "94105", Country: "USA"},
            {Street: "2 Innovation Way", City: "New York", State: "NY", ZipCode: "10001", Country: "USA"},
        },
    }
    
    companyData, _ := json.MarshalIndent(company, "", "  ")
    fmt.Printf("%s\n\n", string(companyData))
    
    // 5. 解码公司
    var decodedCompany Company
    err = json.Unmarshal(companyData, &decodedCompany)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("解码公司:\n")
    fmt.Printf("  名称:%s\n", decodedCompany.Name)
    fmt.Printf("  成立年份:%d\n", decodedCompany.Founded)
    fmt.Printf("  员工数:%d\n", decodedCompany.Employees)
    fmt.Printf("  部门数:%d\n", len(decodedCompany.Departments))
    if decodedCompany.CEO != nil {
        fmt.Printf("  CEO: %s\n", decodedCompany.CEO.Username)
    }
    fmt.Printf("  办公室:%d 个\n", len(decodedCompany.Offices))
    
    // 6. 访问 map 数据
    fmt.Println("\n6. 访问 Map 数据:")
    
    if meta, ok := decoded.Metadata["hobbies"].([]interface{}); ok {
        fmt.Printf("爱好:")
        for _, hobby := range meta {
            fmt.Printf("%s ", hobby.(string))
        }
        fmt.Println()
    }
}

输出

=== 复杂数据结构 ===

2. 编码嵌套结构:
{
  "id": 1,
  "username": "john_doe",
  "email": "john@example.com",
  "created_at": "2024-01-15T10:30:00Z",
  "address": {
    "street": "123 Main St",
    "city": "New York",
    "state": "NY",
    "zip_code": "10001",
    "country": "USA"
  },
  "contacts": [
    {
      "type": "phone",
      "value": "+1-555-1234"
    },
    {
      "type": "email",
      "value": "john.doe@example.com"
    }
  ],
  "metadata": {
    "age": 30,
    "hobbies": [
      "reading",
      "coding"
    ],
    "married": true
  }
}

3. 解码嵌套结构:
解码用户:
  用户名:john_doe
  城市:New York
  联系方式:2 个
  元数据年龄:30

4. 公司结构:
{
  "name": "TechCorp",
  "founded": 2010,
  "employees": 500,
  "departments": [
    "Engineering",
    "Sales",
    "Marketing"
  ],
  "ceo": {
    "id": 1,
    "username": "john_doe",
    ...
  },
  "offices": [
    {
      "street": "1 Tech Plaza",
      "city": "San Francisco",
      ...
    },
    ...
  ]
}

解码公司:
  名称:TechCorp
  成立年份:2010
  员工数:500
  部门数:3
  CEO: john_doe
  办公室:2 个

6. 访问 Map 数据:
爱好:reading coding 

示例 4:流式编解码

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "os"
    "strings"
)

// Message 消息
type Message struct {
    ID      int    `json:"id"`
    Content string `json:"content"`
    Type    string `json:"type"`
}

func main() {
    fmt.Println("=== 流式编解码 ===\n")
    
    // 1. 流式编码
    fmt.Println("1. 流式编码:")
    
    messages := []Message{
        {ID: 1, Content: "Hello", Type: "text"},
        {ID: 2, Content: "World", Type: "text"},
        {ID: 3, Content: "Test", Type: "data"},
    }
    
    var buf strings.Builder
    encoder := json.NewEncoder(&buf)
    
    // 编码多个值
    for _, msg := range messages {
        err := encoder.Encode(msg)
        if err != nil {
            log.Fatal(err)
        }
    }
    
    fmt.Printf("编码结果:\n%s", buf.String())
    
    // 2. 流式解码
    fmt.Println("2. 流式解码:")
    
    decoder := json.NewDecoder(strings.NewReader(buf.String()))
    
    for {
        var msg Message
        err := decoder.Decode(&msg)
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatal(err)
        }
        
        fmt.Printf("  消息 %d: [%s] %s\n", msg.ID, msg.Type, msg.Content)
    }
    
    // 3. 使用 More() 检查
    fmt.Println("\n3. 使用 More() 检查:")
    
    jsonArray := `[{"id":1},{"id":2},{"id":3}]`
    decoder = json.NewDecoder(strings.NewReader(jsonArray))
    
    // 读取数组开始
    decoder.Token()
    
    count := 0
    for decoder.More() {
        var m map[string]interface{}
        decoder.Decode(&m)
        count++
    }
    
    // 读取数组结束
    decoder.Token()
    
    fmt.Printf("  解码了 %d 个对象\n\n", count)
    
    // 4. 使用 Token() 解析
    fmt.Println("4. 使用 Token() 解析:")
    
    complexJSON := `{
        "users": [
            {"name": "Alice", "age": 30},
            {"name": "Bob", "age": 25}
        ],
        "count": 2
    }`
    
    decoder = json.NewDecoder(strings.NewReader(complexJSON))
    
    for {
        token, err := decoder.Token()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatal(err)
        }
        
        fmt.Printf("  Token: %v (类型:%T)\n", token, token)
    }
    
    // 5. 文件流式处理
    fmt.Println("\n5. 文件流式处理:")
    
    // 写入文件
    file, err := os.Create("messages.jsonl")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    
    encoder = json.NewEncoder(file)
    for i := 1; i <= 5; i++ {
        encoder.Encode(Message{ID: i, Content: fmt.Sprintf("Message %d", i), Type: "info"})
    }
    
    fmt.Printf("  ✓ 已写入 messages.jsonl\n")
    
    // 读取文件
    file2, err := os.Open("messages.jsonl")
    if err != nil {
        log.Fatal(err)
    }
    defer file2.Close()
    
    decoder = json.NewDecoder(file2)
    fmt.Println("  读取消息:")
    
    for {
        var msg Message
        err := decoder.Decode(&msg)
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatal(err)
        }
        
        fmt.Printf("    [%d] %s\n", msg.ID, msg.Content)
    }
    
    // 清理
    os.Remove("messages.jsonl")
}

输出

=== 流式编解码 ===

1. 流式编码:
编码结果:
{"id":1,"content":"Hello","type":"text"}
{"id":2,"content":"World","type":"text"}
{"id":3,"content":"Test","type":"data"}

2. 流式解码:
  消息 1: [text] Hello
  消息 2: [text] World
  消息 3: [data] Test

3. 使用 More() 检查:
  解码了 3 个对象

4. 使用 Token() 解析:
  Token: { (类型:json.Delim)
  Token: users (类型:string)
  Token: [ (类型:json.Delim)
  Token: { (类型:json.Delim)
  Token: name (类型:string)
  Token: Alice (类型:string)
  Token: age (类型:string)
  Token: 30 (类型:float64)
  Token: } (类型:json.Delim)
  Token: { (类型:json.Delim)
  Token: name (类型:string)
  Token: Bob (类型:string)
  Token: age (类型:string)
  Token: 25 (类型:float64)
  Token: } (类型:json.Delim)
  Token: ] (类型:json.Delim)
  Token: count (类型:string)
  Token: 2 (类型:float64)
  Token: } (类型:json.Delim)

5. 文件流式处理:
  ✓ 已写入 messages.jsonl
  读取消息:
    [1] Message 1
    [2] Message 2
    [3] Message 3
    [4] Message 4
    [5] Message 5

示例 5:接口和自定义类型

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "strconv"
)

// Shape 形状接口
type Shape interface {
    Area() float64
}

// Circle 圆形
type Circle struct {
    Type   string  `json:"type"`
    Radius float64 `json:"radius"`
}

func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

// Rectangle 矩形
type Rectangle struct {
    Type   string  `json:"type"`
    Width  float64 `json:"width"`
    Height float64 `json:"height"`
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// CustomInt 自定义整数类型
type CustomInt int

// MarshalJSON 自定义编码
func (c CustomInt) MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf("\"%d\"", c)), nil
}

// UnmarshalJSON 自定义解码
func (c *CustomInt) UnmarshalJSON(data []byte) error {
    // 移除引号
    s := string(data)
    if len(s) >= 2 && s[0] == '"' && s[len(s)-1] == '"' {
        s = s[1 : len(s)-1]
    }
    
    val, err := strconv.Atoi(s)
    if err != nil {
        return err
    }
    
    *c = CustomInt(val)
    return nil
}

// Data 包含自定义类型
type Data struct {
    ID       CustomInt `json:"id"`
    Name     string    `json:"name"`
    Value    int       `json:"value"`
}

func main() {
    fmt.Println("=== 接口和自定义类型 ===\n")
    
    // 1. 接口类型编码
    fmt.Println("1. 接口类型编码:")
    
    shapes := []Shape{
        Circle{Type: "circle", Radius: 5.0},
        Rectangle{Type: "rectangle", Width: 4.0, Height: 6.0},
        Circle{Type: "circle", Radius: 3.0},
    }
    
    // 直接编码接口会丢失类型信息
    // 需要手动处理
    type ShapeWrapper struct {
        Type   string      `json:"type"`
        Radius float64     `json:"radius,omitempty"`
        Width  float64     `json:"width,omitempty"`
        Height float64     `json:"height,omitempty"`
    }
    
    for _, shape := range shapes {
        var wrapper ShapeWrapper
        
        switch s := shape.(type) {
        case Circle:
            wrapper = ShapeWrapper{Type: "circle", Radius: s.Radius}
        case Rectangle:
            wrapper = ShapeWrapper{Type: "rectangle", Width: s.Width, Height: s.Height}
        }
        
        data, _ := json.Marshal(wrapper)
        fmt.Printf("  %s\n", string(data))
    }
    
    // 2. 接口类型解码
    fmt.Println("\n2. 接口类型解码:")
    
    jsonShapes := []string{
        `{"type":"circle","radius":5.0}`,
        `{"type":"rectangle","width":4.0,"height":6.0}`,
    }
    
    for _, jsonStr := range jsonShapes {
        var wrapper ShapeWrapper
        json.Unmarshal([]byte(jsonStr), &wrapper)
        
        var shape Shape
        switch wrapper.Type {
        case "circle":
            shape = Circle{Type: wrapper.Type, Radius: wrapper.Radius}
        case "rectangle":
            shape = Rectangle{Type: wrapper.Type, Width: wrapper.Width, Height: wrapper.Height}
        }
        
        fmt.Printf("  类型:%s, 面积:%.2f\n", wrapper.Type, shape.Area())
    }
    
    // 3. 自定义类型编码
    fmt.Println("\n3. 自定义类型编解码:")
    
    data := Data{
        ID:    123,
        Name:  "Test",
        Value: 456,
    }
    
    jsonData, err := json.MarshalIndent(data, "", "  ")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("编码:\n%s\n\n", string(jsonData))
    
    // 4. 自定义类型解码
    fmt.Println("4. 自定义类型解码:")
    
    jsonInput := `{
        "id": "789",
        "name": "Custom",
        "value": 999
    }`
    
    var decoded Data
    err = json.Unmarshal([]byte(jsonInput), &decoded)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("解码:\n")
    fmt.Printf("  ID: %d (类型:%T)\n", decoded.ID, decoded.ID)
    fmt.Printf("  Name: %s\n", decoded.Name)
    fmt.Printf("  Value: %d\n\n", decoded.Value)
    
    // 5. RawMessage 延迟解码
    fmt.Println("5. RawMessage 延迟解码:")
    
    type Event struct {
        Type    string          `json:"type"`
        Payload json.RawMessage `json:"payload"`
    }
    
    eventJSON := `{
        "type": "user_created",
        "payload": {"id": 1, "name": "Alice", "email": "alice@example.com"}
    }`
    
    var event Event
    json.Unmarshal([]byte(eventJSON), &event)
    
    fmt.Printf("事件类型:%s\n", event.Type)
    fmt.Printf("原始 Payload: %s\n", string(event.Payload))
    
    // 延迟解码 Payload
    var payload map[string]interface{}
    json.Unmarshal(event.Payload, &payload)
    
    fmt.Printf("解码 Payload:\n")
    fmt.Printf("  ID: %v\n", payload["id"])
    fmt.Printf("  Name: %v\n", payload["name"])
    fmt.Printf("  Email: %v\n", payload["email"])
}

输出

=== 接口和自定义类型 ===

1. 接口类型编码:
  {"type":"circle","radius":5}
  {"type":"rectangle","width":4,"height":6}
  {"type":"circle","radius":3}

2. 接口类型解码:
  类型:circle, 面积:78.54
  类型:rectangle, 面积:24.00

3. 自定义类型编解码:
编码:
{
  "id": "123",
  "name": "Test",
  "value": 456
}

4. 自定义类型解码:
解码:
  ID: 789 (类型:main.CustomInt)
  Name: Custom
  Value: 999

5. RawMessage 延迟解码:
事件类型:user_created
原始 Payload: {"id": 1, "name": "Alice", "email": "alice@example.com"}
解码 Payload:
  ID: 1
  Name: Alice
  Email: alice@example.com

示例 6:错误处理

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

// User 用户
type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
    Age   int    `json:"age"`
}

func main() {
    fmt.Println("=== JSON 错误处理 ===\n")
    
    // 1. 无效 JSON 语法
    fmt.Println("1. 无效 JSON 语法:")
    
    invalidJSONs := []string{
        `{"name": "John",}`,   // 尾随逗号
        `{"name": "John"}`,    // 缺少右括号
        `{"name": 'John'}`,    // 单引号
        `{name: "John"}`,      // 未加引号的键
        `{"name": "John"`,     // 缺少右大括号
    }
    
    for i, jsonStr := range invalidJSONs {
        var user User
        err := json.Unmarshal([]byte(jsonStr), &user)
        fmt.Printf("  测试 %d: %s\n", i+1, jsonStr)
        if err != nil {
            fmt.Printf("    ✗ 错误:%v\n\n", err)
        } else {
            fmt.Printf("    ✓ 成功(意外)\n\n")
        }
    }
    
    // 2. 类型不匹配
    fmt.Println("2. 类型不匹配:")
    
    typeMismatchCases := []struct {
        json        string
        description string
    }{
        {`{"id": "not_a_number", "name": "John", "email": "john@example.com", "age": 30}`, "ID 应为整数"},
        {`{"id": 1, "name": 123, "email": "john@example.com", "age": 30}`, "Name 应为字符串"},
        {`{"id": 1, "name": "John", "email": "john@example.com", "age": "thirty"}`, "Age 应为整数"},
    }
    
    for _, tc := range typeMismatchCases {
        var user User
        err := json.Unmarshal([]byte(tc.json), &user)
        fmt.Printf("  %s:\n", tc.description)
        fmt.Printf("    JSON: %s\n", tc.json)
        if err != nil {
            fmt.Printf("    ✗ 错误:%v\n\n", err)
        } else {
            fmt.Printf("    ✓ 成功(Go 会尝试转换)\n\n")
        }
    }
    
    // 3. 字段缺失和多余
    fmt.Println("3. 字段缺失和多余:")
    
    // 字段缺失(不会报错)
    missingField := `{"id": 1, "name": "John"}`
    var user1 User
    err := json.Unmarshal([]byte(missingField), &user1)
    fmt.Printf("  字段缺失:\n")
    fmt.Printf("    JSON: %s\n", missingField)
    if err != nil {
        fmt.Printf("    ✗ 错误:%v\n", err)
    } else {
        fmt.Printf("    ✓ 成功(缺失字段为零值)\n")
        fmt.Printf("    结果:%+v\n\n", user1)
    }
    
    // 字段多余(不会报错)
    extraField := `{"id": 1, "name": "John", "email": "john@example.com", "age": 30, "extra": "ignored"}`
    var user2 User
    err = json.Unmarshal([]byte(extraField), &user2)
    fmt.Printf("  字段多余:\n")
    fmt.Printf("    JSON: %s\n", extraField)
    if err != nil {
        fmt.Printf("    ✗ 错误:%v\n", err)
    } else {
        fmt.Printf("    ✓ 成功(多余字段被忽略)\n")
        fmt.Printf("    结果:%+v\n\n", user2)
    }
    
    // 4. 空值和零值
    fmt.Println("4. 空值和零值:")
    
    nullJSON := `{"id": null, "name": null, "email": null, "age": null}`
    var user3 User
    err = json.Unmarshal([]byte(nullJSON), &user3)
    fmt.Printf("  null 值:\n")
    fmt.Printf("    JSON: %s\n", nullJSON)
    if err != nil {
        fmt.Printf("    ✗ 错误:%v\n", err)
    } else {
        fmt.Printf("    ✓ 成功(null 转换为零值)\n")
        fmt.Printf("    结果:%+v\n\n", user3)
    }
    
    // 5. 数组与切片不匹配
    fmt.Println("5. 数组与切片不匹配:")
    
    type Data struct {
        Array [3]int   `json:"array"`
        Slice []int    `json:"slice"`
    }
    
    arrayMismatch := `{"array": [1, 2, 3, 4, 5], "slice": [1, 2, 3]}`
    var data Data
    err = json.Unmarshal([]byte(arrayMismatch), &data)
    fmt.Printf("  数组长度不匹配:\n")
    fmt.Printf("    JSON: %s\n", arrayMismatch)
    if err != nil {
        fmt.Printf("    ✗ 错误:%v\n", err)
    } else {
        fmt.Printf("    ✓ 成功(超出部分被忽略)\n")
        fmt.Printf("    结果:Array=%v, Slice=%v\n\n", data.Array, data.Slice)
    }
    
    // 6. 验证 JSON
    fmt.Println("6. 验证 JSON:")
    
    testCases := []struct {
        json  string
        valid bool
    }{
        {`{"valid": true}`, true},
        {`[1, 2, 3]`, true},
        {`"string"`, true},
        {`123`, true},
        {`true`, true},
        {`null`, true},
        {`{invalid}`, false},
        {`[unclosed`, false},
        {``, false},
    }
    
    for _, tc := range testCases {
        isValid := json.Valid([]byte(tc.json))
        status := "✓"
        if isValid != tc.valid {
            status = "✗"
        }
        fmt.Printf("  %s %s (预期:%v, 实际:%v)\n", status, tc.json, tc.valid, isValid)
    }
    
    // 7. Decoder 错误
    fmt.Println("\n7. Decoder 错误:")
    
    decoder := json.NewDecoder(strings.NewReader(`{invalid}`))
    var result interface{}
    err = decoder.Decode(&result)
    if err != nil {
        fmt.Printf("  ✓ 捕获错误:%v\n", err)
    }
}

输出

=== JSON 错误处理 ===

1. 无效 JSON 语法:
  测试 1: {"name": "John",}
    ✗ 错误:invalid character '}' looking for beginning of object key string

  测试 2: {"name": "John"}
    ✓ 成功(意外)

  测试 3: {"name": 'John'}
    ✗ 错误:invalid character '\'' looking for beginning of object key string

  测试 4: {name: "John"}
    ✗ 错误:invalid character 'n' looking for beginning of object key string

  测试 5: {"name": "John"
    ✗ 错误:unexpected end of JSON input

2. 类型不匹配:
  ID 应为整数:
    JSON: {"id": "not_a_number", "name": "John", "email": "john@example.com", "age": 30}
    ✗ 错误:json: cannot unmarshal string into Go struct field User.id of type int

  Name 应为字符串:
    JSON: {"id": 1, "name": 123, "email": "john@example.com", "age": 30}
    ✗ 错误:json: cannot unmarshal number into Go struct field User.name of type string

  Age 应为整数:
    JSON: {"id": 1, "name": "John", "email": "john@example.com", "age": "thirty"}
    ✗ 错误:json: cannot unmarshal string into Go struct field User.age of type int

3. 字段缺失和多余:
  字段缺失:
    JSON: {"id": 1, "name": "John"}
    ✓ 成功(缺失字段为零值)
    结果:{ID:1 Name:John Email: Age:0}

  字段多余:
    JSON: {"id": 1, "name": "John", "email": "john@example.com", "age": 30, "extra": "ignored"}
    ✓ 成功(多余字段被忽略)
    结果:{ID:1 Name:John Email:john@example.com Age:30}

4. 空值和零值:
  null 值:
    JSON: {"id": null, "name": null, "email": null, "age": null}
    ✓ 成功(null 转换为零值)
    结果:{ID:0 Name: Email: Age:0}

5. 数组与切片不匹配:
  数组长度不匹配:
    JSON: {"array": [1, 2, 3, 4, 5], "slice": [1, 2, 3]}
    ✓ 成功(超出部分被忽略)
    结果:Array=[1 2 3], Slice=[1 2 3]

6. 验证 JSON:
  ✓ {"valid": true} (预期:true, 实际:true)
  ✓ [1, 2, 3] (预期:true, 实际:true)
  ✓ "string" (预期:true, 实际:true)
  ✓ 123 (预期:true, 实际:true)
  ✓ true (预期:true, 实际:true)
  ✓ null (预期:true, 实际:true)
  ✓ {invalid} (预期:false, 实际:false)
  ✓ [unclosed (预期:false, 实际:false)
  ✓  (预期:false, 实际:false)

7. Decoder 错误:
  ✓ 捕获错误:invalid character 'i' looking for beginning of object key string

示例 7:Web API 应用

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "net/http"
    "strings"
)

// User 用户
type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Email    string `json:"email"`
    Age      int    `json:"age,omitempty"`
}

// Response API 响应
type Response struct {
    Success bool        `json:"success"`
    Message string      `json:"message"`
    Data    interface{} `json:"data,omitempty"`
    Error   string      `json:"error,omitempty"`
}

// ErrorResponse 错误响应
type ErrorResponse struct {
    Success bool   `json:"success"`
    Error   string `json:"error"`
    Code    int    `json:"code"`
}

// 模拟用户数据库
var users = map[int]User{
    1: {ID: 1, Username: "alice", Email: "alice@example.com", Age: 30},
    2: {ID: 2, Username: "bob", Email: "bob@example.com", Age: 25},
    3: {ID: 3, Username: "charlie", Email: "charlie@example.com", Age: 35},
}

var nextID = 4

// WriteJSON 写入 JSON 响应
func WriteJSON(w http.ResponseWriter, status int, data interface{}) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(status)
    json.NewEncoder(w).Encode(data)
}

// WriteError 写入错误响应
func WriteError(w http.ResponseWriter, status int, message string, code int) {
    WriteJSON(w, status, ErrorResponse{
        Success: false,
        Error:   message,
        Code:    code,
    })
}

// GetUser 获取用户
func GetUser(w http.ResponseWriter, r *http.Request) {
    // 从 URL 获取 ID
    idStr := strings.TrimPrefix(r.URL.Path, "/users/")
    if idStr == "" {
        WriteError(w, http.StatusBadRequest, "Missing user ID", 4001)
        return
    }
    
    // 解析 ID(简化示例)
    var id int
    fmt.Sscanf(idStr, "%d", &id)
    
    user, exists := users[id]
    if !exists {
        WriteError(w, http.StatusNotFound, "User not found", 4002)
        return
    }
    
    WriteJSON(w, http.StatusOK, Response{
        Success: true,
        Message: "User retrieved successfully",
        Data:    user,
    })
}

// CreateUser 创建用户
func CreateUser(w http.ResponseWriter, r *http.Request) {
    // 读取请求体
    body, err := io.ReadAll(r.Body)
    if err != nil {
        WriteError(w, http.StatusBadRequest, "Invalid request body", 4003)
        return
    }
    defer r.Body.Close()
    
    // 解码 JSON
    var input struct {
        Username string `json:"username"`
        Email    string `json:"email"`
        Age      int    `json:"age,omitempty"`
    }
    
    err = json.Unmarshal(body, &input)
    if err != nil {
        WriteError(w, http.StatusBadRequest, "Invalid JSON: "+err.Error(), 4004)
        return
    }
    
    // 验证
    if input.Username == "" || input.Email == "" {
        WriteError(w, http.StatusBadRequest, "Username and email are required", 4005)
        return
    }
    
    // 创建用户
    user := User{
        ID:       nextID,
        Username: input.Username,
        Email:    input.Email,
        Age:      input.Age,
    }
    nextID++
    
    users[user.ID] = user
    
    WriteJSON(w, http.StatusCreated, Response{
        Success: true,
        Message: "User created successfully",
        Data:    user,
    })
}

// ListUsers 列出所有用户
func ListUsers(w http.ResponseWriter, r *http.Request) {
    userList := make([]User, 0, len(users))
    for _, user := range users {
        userList = append(userList, user)
    }
    
    WriteJSON(w, http.StatusOK, Response{
        Success: true,
        Message: "Users retrieved successfully",
        Data:    userList,
    })
}

// UserHandler 用户处理函数
func UserHandler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet:
        if r.URL.Path == "/users" {
            ListUsers(w, r)
        } else {
            GetUser(w, r)
        }
    case http.MethodPost:
        CreateUser(w, r)
    default:
        WriteError(w, http.StatusMethodNotAllowed, "Method not allowed", 4006)
    }
}

// main 示例(不实际运行服务器)
func main() {
    fmt.Println("=== Web API 应用 ===\n")
    
    // 模拟请求测试
    fmt.Println("1. 获取用户列表:")
    var listResp Response
    jsonData := `{"success":true,"message":"Users retrieved successfully","data":[{"id":1,"username":"alice","email":"alice@example.com","age":30},{"id":2,"username":"bob","email":"bob@example.com","age":25}]}`
    json.Unmarshal([]byte(jsonData), &listResp)
    fmt.Printf("  成功:%v\n", listResp.Success)
    if users, ok := listResp.Data.([]interface{}); ok {
        fmt.Printf("  用户数:%d\n\n", len(users))
    }
    
    fmt.Println("2. 获取单个用户:")
    var getResp Response
    jsonData = `{"success":true,"message":"User retrieved successfully","data":{"id":1,"username":"alice","email":"alice@example.com","age":30}}`
    json.Unmarshal([]byte(jsonData), &getResp)
    fmt.Printf("  成功:%v\n", getResp.Success)
    fmt.Printf("  消息:%s\n\n", getResp.Message)
    
    fmt.Println("3. 创建用户响应:")
    var createResp Response
    jsonData = `{"success":true,"message":"User created successfully","data":{"id":4,"username":"david","email":"david@example.com"}}`
    json.Unmarshal([]byte(jsonData), &createResp)
    fmt.Printf("  成功:%v\n", createResp.Success)
    fmt.Printf("  消息:%s\n\n", createResp.Message)
    
    fmt.Println("4. 错误响应:")
    var errorResp ErrorResponse
    jsonData = `{"success":false,"error":"User not found","code":4002}``
    json.Unmarshal([]byte(jsonData), &errorResp)
    fmt.Printf("  成功:%v\n", errorResp.Success)
    fmt.Printf("  错误:%s\n", errorResp.Error)
    fmt.Printf("  代码:%d\n\n", errorResp.Code)
    
    fmt.Println("✓ Web API 示例完成")
    fmt.Println("\n实际使用时,运行:")
    fmt.Println("  http.HandleFunc(\"/users\", UserHandler)")
    fmt.Println("  http.ListenAndServe(\":8080\", nil)")
}

输出

=== Web API 应用 ===

1. 获取用户列表:
  成功:true
  用户数:2

2. 获取单个用户:
  成功:true
  消息:User retrieved successfully

3. 创建用户响应:
  成功:true
  消息:User created successfully

4. 错误响应:
  成功:false
  错误:User not found
  代码:4002

✓ Web API 示例完成

实际使用时,运行:
  http.HandleFunc("/users", UserHandler)
  http.ListenAndServe(":8080", nil)

示例 8:配置文件处理

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "os"
)

// Config 配置结构
type Config struct {
    App      AppConfig      `json:"app"`
    Database DatabaseConfig `json:"database"`
    Server   ServerConfig   `json:"server"`
    Features []string       `json:"features"`
}

// AppConfig 应用配置
type AppConfig struct {
    Name    string `json:"name"`
    Version string `json:"version"`
    Debug   bool   `json:"debug"`
}

// DatabaseConfig 数据库配置
type DatabaseConfig struct {
    Host     string `json:"host"`
    Port     int    `json:"port"`
    User     string `json:"user"`
    Password string `json:"password"`
    Database string `json:"database"`
    SSL      bool   `json:"ssl"`
}

// ServerConfig 服务器配置
type ServerConfig struct {
    Host         string   `json:"host"`
    Port         int      `json:"port"`
    ReadTimeout  int      `json:"read_timeout"`
    WriteTimeout int      `json:"write_timeout"`
    AllowedOrigins []string `json:"allowed_origins"`
}

// LoadConfig 加载配置文件
func LoadConfig(filename string) (*Config, error) {
    file, err := os.Open(filename)
    if err != nil {
        return nil, err
    }
    defer file.Close()
    
    var config Config
    decoder := json.NewDecoder(file)
    err = decoder.Decode(&config)
    if err != nil {
        return nil, err
    }
    
    return &config, nil
}

// SaveConfig 保存配置文件
func SaveConfig(filename string, config *Config) error {
    file, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer file.Close()
    
    encoder := json.NewEncoder(file)
    encoder.SetIndent("", "  ")
    return encoder.Encode(config)
}

// DefaultConfig 默认配置
func DefaultConfig() *Config {
    return &Config{
        App: AppConfig{
            Name:    "MyApp",
            Version: "1.0.0",
            Debug:   false,
        },
        Database: DatabaseConfig{
            Host:     "localhost",
            Port:     5432,
            User:     "admin",
            Password: "secret",
            Database: "mydb",
            SSL:      false,
        },
        Server: ServerConfig{
            Host:         "0.0.0.0",
            Port:         8080,
            ReadTimeout:  30,
            WriteTimeout: 30,
            AllowedOrigins: []string{"*"},
        },
        Features: []string{"feature1", "feature2"},
    }
}

func main() {
    fmt.Println("=== 配置文件处理 ===\n")
    
    // 1. 创建默认配置
    fmt.Println("1. 创建默认配置:")
    config := DefaultConfig()
    
    // 2. 保存配置
    fmt.Println("2. 保存配置到 config.json:")
    err := SaveConfig("config.json", config)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("  ✓ 配置已保存\n")
    
    // 3. 加载配置
    fmt.Println("3. 从 config.json 加载配置:")
    loadedConfig, err := LoadConfig("config.json")
    if err != nil {
        log.Fatal(err)
    }
    
    // 4. 显示配置
    fmt.Printf("  应用名称:%s\n", loadedConfig.App.Name)
    fmt.Printf("  版本:%s\n", loadedConfig.App.Version)
    fmt.Printf("  调试模式:%v\n", loadedConfig.App.Debug)
    fmt.Printf("  数据库:%s@%s:%d/%s\n", 
        loadedConfig.Database.User,
        loadedConfig.Database.Host,
        loadedConfig.Database.Port,
        loadedConfig.Database.Database)
    fmt.Printf("  服务器端口:%d\n", loadedConfig.Server.Port)
    fmt.Printf("  功能:%v\n\n", loadedConfig.Features)
    
    // 5. 显示原始 JSON
    fmt.Println("4. 配置文件内容:")
    content, _ := os.ReadFile("config.json")
    fmt.Printf("%s\n", string(content))
    
    // 6. 修改配置
    fmt.Println("5. 修改配置:")
    loadedConfig.App.Debug = true
    loadedConfig.Server.Port = 9090
    loadedConfig.Features = append(loadedConfig.Features, "feature3")
    
    SaveConfig("config_updated.json", loadedConfig)
    fmt.Println("  ✓ 配置已更新到 config_updated.json\n")
    
    // 清理
    os.Remove("config.json")
    os.Remove("config_updated.json")
    
    fmt.Println("✓ 配置文件处理示例完成")
}

输出

=== 配置文件处理 ===

1. 创建默认配置:
2. 保存配置到 config.json:
  ✓ 配置已保存

3. 从 config.json 加载配置:
  应用名称:MyApp
  版本:1.0.0
  调试模式:false
  数据库:admin@localhost:5432/mydb
  服务器端口:8080
  功能:[feature1 feature2]

4. 配置文件内容:
{
  "app": {
    "name": "MyApp",
    "version": "1.0.0",
    "debug": false
  },
  "database": {
    "host": "localhost",
    "port": 5432,
    "user": "admin",
    "password": "secret",
    "database": "mydb",
    "ssl": false
  },
  "server": {
    "host": "0.0.0.0",
    "port": 8080,
    "read_timeout": 30,
    "write_timeout": 30,
    "allowed_origins": [
      "*"
    ]
  },
  "features": [
    "feature1",
    "feature2"
  ]
}

5. 修改配置:
  ✓ 配置已更新到 config_updated.json

✓ 配置文件处理示例完成

示例 9:UseNumber 处理大数字

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "strings"
)

func main() {
    fmt.Println("=== UseNumber 处理大数字 ===\n")
    
    // 大数字 JSON
    jsonStr := `{
        "small": 123,
        "large": 9223372036854775807,
        "larger": 9223372036854775808,
        "huge": 123456789012345678901234567890,
        "float": 123.456
    }`
    
    // 1. 默认解码(使用 float64)
    fmt.Println("1. 默认解码 (float64):")
    var data1 map[string]interface{}
    err := json.Unmarshal([]byte(jsonStr), &data1)
    if err != nil {
        log.Fatal(err)
    }
    
    for key, value := range data1 {
        fmt.Printf("  %s: %v (类型:%T)\n", key, value, value)
    }
    
    // 检查精度丢失
    fmt.Printf("\n  精度检查:\n")
    large := data1["large"].(float64)
    larger := data1["larger"].(float64)
    fmt.Printf("  large == larger: %v (可能丢失精度)\n", large == larger)
    
    // 2. 使用 UseNumber()
    fmt.Println("\n2. 使用 UseNumber():")
    decoder := json.NewDecoder(strings.NewReader(jsonStr))
    decoder.UseNumber()
    
    var data2 map[string]interface{}
    err = decoder.Decode(&data2)
    if err != nil {
        log.Fatal(err)
    }
    
    for key, value := range data2 {
        fmt.Printf("  %s: %v (类型:%T)\n", key, value, value)
    }
    
    // 3. 数字转换
    fmt.Println("\n3. 数字转换:")
    largeNum := data2["large"].(json.Number)
    largerNum := data2["larger"].(json.Number)
    hugeNum := data2["huge"].(json.Number)
    
    // 转换为 int64
    if i64, err := largeNum.Int64(); err == nil {
        fmt.Printf("  large (int64): %d\n", i64)
    } else {
        fmt.Printf("  large (int64): 错误 - %v\n", err)
    }
    
    if i64, err := largerNum.Int64(); err == nil {
        fmt.Printf("  larger (int64): %d\n", i64)
    } else {
        fmt.Printf("  larger (int64): 错误 - %v\n", err)
    }
    
    // 转换为 float64
    if f64, err := largeNum.Float64(); err == nil {
        fmt.Printf("  large (float64): %.0f\n", f64)
    }
    
    // 转换为字符串
    fmt.Printf("  huge (string): %s\n", hugeNum.String())
    
    // 4. 精度比较
    fmt.Println("\n4. 精度比较:")
    fmt.Printf("  默认解码 large == larger: %v\n", large == larger)
    fmt.Printf("  UseNumber large == larger: %v\n", largeNum.String() == largerNum.String())
    fmt.Printf("  large: %s\n", largeNum.String())
    fmt.Printf("  larger: %s\n", largerNum.String())
}

输出

=== UseNumber 处理大数字 ===

1. 默认解码 (float64):
  small: 123 (类型:float64)
  large: 9.223372036854776e+18 (类型:float64)
  larger: 9.223372036854776e+18 (类型:float64)
  huge: 1.2345678901234568e+29 (类型:float64)
  float: 123.456 (类型:float64)

  精度检查:
  large == larger: true (可能丢失精度)

2. 使用 UseNumber():
  small: 123 (类型:json.Number)
  large: 9223372036854775807 (类型:json.Number)
  larger: 9223372036854775808 (类型:json.Number)
  huge: 123456789012345678901234567890 (类型:json.Number)
  float: 123.456 (类型:json.Number)

3. 数字转换:
  large (int64): 9223372036854775807
  larger (int64): 错误 - json: invalid number
  large (float64): 9223372036854775807
  huge (string): 123456789012345678901234567890

4. 精度比较:
  默认解码 large == larger: true
  UseNumber large == larger: false
  large: 9223372036854775807
  larger: 9223372036854775808

示例 10:Map 和 Slice 的高级用法

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

func main() {
    fmt.Println("=== Map 和 Slice 高级用法 ===\n")
    
    // 1. Map 的编解码
    fmt.Println("1. Map 编解码:")
    
    config := map[string]interface{}{
        "name":     "MyApp",
        "version":  "1.0.0",
        "port":     8080,
        "debug":    true,
        "features": []string{"auth", "logging", "cache"},
        "database": map[string]interface{}{
            "host": "localhost",
            "port": 5432,
        },
    }
    
    data, err := json.MarshalIndent(config, "", "  ")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("编码:\n%s\n\n", string(data))
    
    // 解码
    var decoded map[string]interface{}
    err = json.Unmarshal(data, &decoded)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("解码:\n")
    fmt.Printf("  name: %s\n", decoded["name"])
    fmt.Printf("  version: %s\n", decoded["version"])
    fmt.Printf("  port: %v (类型:%T)\n", decoded["port"], decoded["port"])
    fmt.Printf("  debug: %v (类型:%T)\n", decoded["debug"], decoded["debug"])
    
    // 类型断言访问切片
    if features, ok := decoded["features"].([]interface{}); ok {
        fmt.Printf("  features: ")
        for _, f := range features {
            fmt.Printf("%s ", f.(string))
        }
        fmt.Println()
    }
    
    // 类型断言访问嵌套 map
    if db, ok := decoded["database"].(map[string]interface{}); ok {
        fmt.Printf("  database.host: %s\n", db["host"])
        fmt.Printf("  database.port: %v\n", db["port"])
    }
    fmt.Println()
    
    // 2. Slice 的编解码
    fmt.Println("2. Slice 编解码:")
    
    users := []map[string]interface{}{
        {"id": 1, "name": "Alice", "email": "alice@example.com"},
        {"id": 2, "name": "Bob", "email": "bob@example.com"},
        {"id": 3, "name": "Charlie", "email": "charlie@example.com"},
    }
    
    data, err = json.MarshalIndent(users, "", "  ")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("编码:\n%s\n\n", string(data))
    
    // 解码
    var decodedUsers []map[string]interface{}
    err = json.Unmarshal(data, &decodedUsers)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("解码:\n")
    for i, user := range decodedUsers {
        fmt.Printf("  用户 %d: %s (%s)\n", 
            i+1, 
            user["name"].(string), 
            user["email"].(string))
    }
    fmt.Println()
    
    // 3. 有序 Map(使用切片保持顺序)
    fmt.Println("3. 保持顺序:")
    
    type KeyValue struct {
        Key   string      `json:"key"`
        Value interface{} `json:"value"`
    }
    
    orderedConfig := []KeyValue{
        {Key: "z_last", Value: "Should be last"},
        {Key: "a_first", Value: "Should be first"},
        {Key: "m_middle", Value: "Should be middle"},
    }
    
    data, _ = json.MarshalIndent(orderedConfig, "", "  ")
    fmt.Printf("有序配置:\n%s\n\n", string(data))
    
    // 4. 过滤 Map 字段
    fmt.Println("4. 过滤 Map 字段:")
    
    fullData := map[string]interface{}{
        "public":  "visible",
        "private": "hidden",
        "secret":  "very_secret",
    }
    
    // 只导出公共字段
    filtered := make(map[string]interface{})
    for k, v := range fullData {
        if k != "private" && k != "secret" {
            filtered[k] = v
        }
    }
    
    data, _ = json.MarshalIndent(filtered, "", "  ")
    fmt.Printf("过滤后:\n%s\n", string(data))
}

输出

=== Map 和 Slice 高级用法 ===

1. Map 编解码:
编码:
{
  "database": {
    "host": "localhost",
    "port": 5432
  },
  "debug": true,
  "features": [
    "auth",
    "logging",
    "cache"
  ],
  "name": "MyApp",
  "port": 8080,
  "version": "1.0.0"
}

解码:
  name: MyApp
  version: 1.0.0
  port: 8080 (类型:float64)
  debug: true (类型:bool)
  features: auth logging cache 
  database.host: localhost
  database.port: 5432

2. Slice 编解码:
编码:
[
  {
    "id": 1,
    "name": "Alice",
    "email": "alice@example.com"
  },
  {
    "id": 2,
    "name": "Bob",
    "email": "bob@example.com"
  },
  {
    "id": 3,
    "name": "Charlie",
    "email": "charlie@example.com"
  }
]

解码:
  用户 1: Alice (alice@example.com)
  用户 2: Bob (bob@example.com)
  用户 3: Charlie (charlie@example.com)

3. 保持顺序:
有序配置:
[
  {
    "key": "z_last",
    "value": "Should be last"
  },
  {
    "key": "a_first",
    "value": "Should be first"
  },
  {
    "key": "m_middle",
    "value": "Should be middle"
  }
]

4. 过滤 Map 字段:
过滤后:
{
  "public": "visible"
}

最佳实践

✅ 推荐做法

  1. 总是检查错误

    // ✅ 推荐
    data, err := json.Marshal(v)
    if err != nil {
        return err
    }
    
    err = json.Unmarshal(data, &v)
    if err != nil {
        return err
    }
    
    // ❌ 不推荐
    data, _ := json.Marshal(v)
    json.Unmarshal(data, &v)
    
  2. 使用指针接收解码

    // ✅ 推荐
    var user User
    err := json.Unmarshal(data, &user)
    
    // ❌ 错误
    var user User
    err := json.Unmarshal(data, user)  // 需要指针
    
  3. 使用 struct tag 自定义字段

    // ✅ 推荐
    type User struct {
        Name  string `json:"name"`
        Email string `json:"email,omitempty"`
    }
    
    // ❌ 不推荐
    type User struct {
        Name  string  // 默认使用字段名
        Email string
    }
    
  4. 大数字使用 UseNumber()

    // ✅ 推荐:处理大数字或需要精度
    decoder := json.NewDecoder(reader)
    decoder.UseNumber()
    
    // ❌ 不推荐:可能丢失精度
    var data map[string]interface{}
    json.Unmarshal(jsonData, &data)  // 数字转为 float64
    
  5. 流式处理大文件

    // ✅ 推荐:大文件
    decoder := json.NewDecoder(file)
    for decoder.More() {
        var item Item
        decoder.Decode(&item)
    }
    
    // ❌ 不推荐:可能内存溢出
    data, _ := io.ReadAll(file)
    json.Unmarshal(data, &items)
    
  6. 使用 json.Number 处理数字

    // ✅ 推荐
    num := data["count"].(json.Number)
    intVal, _ := num.Int64()
    
    // ❌ 不推荐
    num := data["count"].(float64)  // 可能丢失精度
    

❌ 不安全做法

  1. 不要忽略类型断言

    // ❌ 错误
    value := data["key"].(string)  // 可能 panic
    
    // ✅ 正确
    value, ok := data["key"].(string)
    if !ok {
        // 处理类型不匹配
    }
    
  2. 不要信任输入数据

    // ❌ 错误
    var user User
    json.Unmarshal(input, &user)  // 未验证
    
    // ✅ 正确
    var user User
    if err := json.Unmarshal(input, &user); err != nil {
        return err
    }
    // 验证 user 字段
    
  3. 不要编码敏感数据

    // ❌ 错误
    type User struct {
        Name     string `json:"name"`
        Password string `json:"password"`  // 危险!
    }
    
    // ✅ 正确
    type User struct {
        Name     string `json:"name"`
        Password string `json:"-"`  // 不编码
    }
    

性能优化

1. 使用 MarshalIndent 代替手动格式化

// ✅ 推荐
data, _ := json.MarshalIndent(v, "", "  ")

// ❌ 不推荐
data, _ := json.Marshal(v)
// 然后手动格式化

2. 预分配切片

// ✅ 推荐
items := make([]Item, 0, expectedCount)
json.Unmarshal(data, &items)

// ❌ 不推荐
var items []Item
json.Unmarshal(data, &items)

3. 重用 Encoder/Decoder

// ✅ 推荐:重用
encoder := json.NewEncoder(buf)
for _, item := range items {
    encoder.Encode(item)
}

// ❌ 不推荐:重复创建
for _, item := range items {
    json.NewEncoder(buf).Encode(item)
}

4. 使用 omitempty 减少大小

// ✅ 推荐
type User struct {
    Name  string `json:"name,omitempty"`
    Email string `json:"email,omitempty"`
}

// 零值字段不会被编码

总结

核心函数

函数用途返回值
Marshal编码为 JSON[]byte, error
MarshalIndent格式化编码[]byte, error
Unmarshal从 JSON 解码error
Valid验证 JSONbool
HTMLEscapeHTML 转义-

核心类型

类型用途说明
Encoder流式编码json.NewEncoder(w)
Decoder流式解码json.NewDecoder(r)
RawMessage原始 JSON延迟解码
NumberJSON 数字保持精度
TokenJSON Token对象/数组边界

Struct Tag 选项

选项说明示例
字段名自定义键名json:"name"
omitempty零值忽略json:"name,omitempty"
string数字转字符串json:"age,string"
-忽略字段json:"-"

类型映射

Go 类型JSON 类型
int, floatnumber
stringstring
[]T, map[K]Varray, object
boolboolean
nil, nil pointernull

常见错误

错误原因解决方法
invalid characterJSON 语法错误检查 JSON 格式
cannot unmarshal类型不匹配检查类型定义
unexpected endJSON 不完整检查数据完整性

参考资料


最后更新:2026-04-03
Go 版本:Go 1.23+