开发者

golang中encoding/json包的实现

目录
  • 1. 基本使用
    • 1.1 结构体字段与 jsON 的映射
    • 1.2 序列化与反序列化
  • 2. 自定义 JSON 序列化与反序列化
    • 2.1 自定义类型示例
  • 3. 处理 JSON 数组
    • 3.1 JSON 数组示例
  • 4. 解析任意结构的 JSON 数据
    • 4.1 任意结构 JSON 示例
  • 5. 流式处理 JSON 数据
    • 5.1 使用json.Decoder解码流式 JSON
    • 5.2 使用json.Encoder编码流式 JSON
  • 6. 时间类型的序列化与反序列化
    • 6.1 自定义时间格式示例
  • 总结

    Go www.devze.com语言通过 encoding/json 包提供了对 JSON 数据的强大支持,包括序列化、反序列化、自定义处理、数组处理、任意结构解析以及流式处理等。

    1. 基本使用

    1.1 结构体字段与 JSON 的映射

    在 Go 中,结构体的字段可以通过 json 标签(JSON Tag)与 JSON 字段进行映射。如果不指定 json 标签,默认使用结构体字段名的蛇形命名(小写)作为 JSON 字段名。

    type P struct { // 未使用json标签,自动根据字段名称进行绑定
        Name    string
        Age     int
        Address string
        Sex     string
        Time    time.Time
    }
    
    type Person struct {
        Name    string `json:"name"`
        Age     int    `json:"age"`
        Address string `json:"-"`
        Sex     string `json:"sex,omitempty"`
    }
    
    • 结构体 P:未定义 json 标签,序列化时会使用结构体字段名作为 JSON 字段名。
    • 结构体 Person
      • NameAge 使用 json 标签映射为 nameage
      • Address 使用 - 标签,表示不会被序列化。
      • Sex 使用 omitempty,当字段为空时不会被序列化。

    1.2 序列化与反序列化

    func main() {
        p1 := P{
            Name:    "Jon",
            Age:     20,
            Address: "beijing",
            Sex:     "男",
            Time:    time.Now(),
        }
    
        p2 := Person{
            Name:    "hon",
            Age:     20,
            Address: "beijing",
            Sex:     "",
        }
    
        // 编码(序列化)
        json1, err := json.Marshal(p1)
        // 处理错误
        fmt.Println(string(json1))
        // 输出示例: {"Name":"Jon","Age":20,"Address":"beijing","Sex":"男"python,"Time":"..编程."}
    
        json2, err := json.Marshal(p2)
        // 处理错误
        fmt.Println(string(json2))
        // 输出示例: {"name":"hon","age":20}
    
        // 解码(反序列化)
        var p3 Person
        err = json.Unmarshal(json1, &p3)
        // 处理错误
        fmt.Printf("%+v\n", p3)
        // 输出: {Name:Jon Age:20 Address: Sex:男}
    
        err = json.Unmarshal(json2, &p3)
        // 处理错误
        fmt.Printf("%+v\n", p3)
        // 输出: {Name:hon Age:20 Address: Sex:}
    }
    
    • json.Marshal:将 Go 结构体序列化为 JSON 字符串。
    • json.Unmarshal:将 JSON 字符串反序列化为 Go 结构体。

    2. 自定义 JSON 序列化与反序列化

    有时候,默认的序列化和反序列化方式无法满足需求,这时可以通过实现 MarshalJSONUnmarshalJSON 方法来自定义行为。

    2.1 自定义类型示例

    type Massachusetts struct {
        Name string
    }
    
    type P3 struct {
        Name    string
        Address *Massachusetts
    }
    
    // 自定义 MarshalJSON 方法
    func (m *Massachusetts) MarshalJSON() ([]byte, error) {
        return json.Marshal(struct {
            State string `json:"state"`
        }{
            State: m.Name,
        })
    }
    
    func Customize() {
        address := Massachusetts{Name: "beijing"}
        p := P3{
            Name:    "jon",
            Address: &address,
        }
    
        // 编码
        jsonBytes, err := json.Marshal(p)
        // 处理错误
        fmt.Println(string(jsonBytes))
        // 输出: {"Name":"jon","Address":{"state":"beijing"}}
    }
    
    • Massachusetts 结构体通过自定义 MarshalJSON 方法,将 Name 字段序列化为 state 字段。

    3. 处理 JSON 数组

    Go 中的切片(Slice)和数组(Array)可以很方便地序列化为 JSON 数组,反向亦然。

    3.1 JSON 数组示例

    type P4 struct {
        Name string `json:"name"`
        Age  int    `json:"age"`
    }
    
    func JsonArray() {
        people := []P4{
            {Name: "p1", Age: 22},
            {Name: "p2", Age: 23},
        }
    
        jonsBytes, err := json.Marshal(people)
        // 处理错误
        fmt.Println(string(jonsBytes))
        // 输出: [{"name":"p1","age":22},{"name":"p2","age":23}]
    }
    
    • JsonArray 函数展示了如何将切片序列化为 JSON 数组,以及如何进行反序列化。

    4. 解析任意结构的 JSON 数据

    在处理来自外部系统的 JSON 数据时,通常无法提前知道其具体结构。Go 提供了 map[string]interface{}interface{} 来处理这种情况。

    4.1 任意结构 JSON 示例

    func JsonAny() {
        jsonString := `{
            "name":"p1",
            "Age":21,
            "email":"1.@qq.com"
        }`
    
        var m map[string]interface{}
        err := json.Unmarshal([]byte(jsonString), &m)
        // 处理错误
        fmt.Printf("%+v\n", m)
        // 输出: map[Age:21 email:1.@qq.com name:p1]
    }
    
    • JsonAny 函数展示了如何将任意结构的 JSON 字符串解析为 map[string]interface{},方便后续操作。

    5. 流式处理 JSON 数据

    对于大型 JSON 数据,逐行读写(js流式处理)比一次性加载整个文件更加高效。Go 提供了 json.Decoderjson.Encoder 来处理流式 JSON 数据。

    5.1 使用json.Decoder解码流式 JSON

    func JsonNewDecoder() {
        jsonData := `{"name":"John", "age":23}`
        reader := strings.NewReader(jsonData)
        decoder := json.NewDecoder(reader)
    
        var p P4
        if err := decoder.Decode(&p); err != nil {
            fmt.Println(err)
        }
        fmt.Printf("%+v\n", p)
        // 输出: {Name:John Age:23}
    }
    
    • JsonNewDecoder 函数展示了如何使用 json.Decoderio.Reader 中逐行读取和解析 JSON 数据。

    5.2 使用json.Encoder编码流式 JSON

    func JsonNewEncoder() {
        p := P4{Name: "p1", Age: 22}
        writer := &strings.Builder{}
        encoder := json.NewEncoder(writer)
    
        if err := encoder.Encode(&p); err != nil {
            fmt.Println(err)
        }
        fmt.Println(writer.String())
        // 输出: {"name":"p1","age":22}
    }
    
    • JsonNewEncoder 函数展示了如何使用 json.Encoder 将 Go 数据结构流式写入 io.Writer

    6. 时间类型的序列化与反序列化

    在处理包含时间字段的 JSON 数据时,默认的序列化格式为 RFC3339。如果需要自定义时间格式,可以通过自定义类型实现。

    6.1 自定义时间格式示例

    type CustomTime time.Time
    
    func (ct CustomTime) MarshalJSON() ([]byte, error) {
        return []byte(fmt.Sprintf("\"%s\"", time.Time(ct).Format("2006-01-02 15:04:05"))), nil
    }
    
    func (ct *CustomTime) UnmarshalJSON(b []byte) error {
        str := string(b)
        str = str[1 : len(str)-1] // 去除双引号
        t, err := time.Parse("2006-01-02 15:04:05", str)
        if err != nil {
            return err
        }
        *ct = CustomTime(t)
        return nil
    }
    
    type P5 struct {
        Name      string     `json:"name"`
        CreatedAt CustomTime `json:"created_at"`
    }
    
    func CustomTimeExample() {
        p := P5{
            Name:      "jon",
            CreatedAt: CustomTime(time.Now()),
        }
    
        jsonBytes, err := json.Marshal(p)
        // 处理错误
        fmt.Println(string(jsonBytes))
        // 输出: {"name":"jon","created_at":"2025-04-03 23:48:31"}
    
        var p2 P5
        err = json.Unmarshal(jsonBytes, &p2)
        // 处理错误
        fmt.Printf("%+v\n", p2)
        // 输出: {Name:jon CreatedAt:2025-04-03 23:48:31 +0800php CST}
    }
    
    • CustomTime 类型通过实现自定义的 MarshalJSONUnmarshalJSON 方法,定义了时间的序列化和反序列化格式。

    总结

    Go 语言的 encoding/json 包提供了灵活而强大的工具来处理 JSON 数据。无论是基本的序列化和反序列化,还是复杂的自定义行为、数组处理、任意结构解析以及流式处理,encoding/json 都能很好地满足需求。理解并掌握这些功能,有助于在开发中高效地处理各种 JSON 数据相关的任务。

    到此这篇关于golang中encoding/json包的实现的文章就介绍到这了,更多相关golang encoding/json包内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜