Json处理

encoding/json为官方自带JSON处理包。提供了对JSON数据的编码和解码功能,可以方便地将Go数据结构转换为JSON格式(称为序列化或编码),以及将JSON数据转换为Go数据结构(称为反序列化或解码)。

1 序列化

  • 将 Go 结构体、map 或基本类型序列化为 JSON 字节切片。

  • json.Marshal(v interface{}) ([]byte, error)

注意事项​​:

  • 只有公开字段可序列化

  • 字段可通过标签定制

  • 循环引用会报错

  • 默认开启HTML转义

// 结构体和JSON映射  
type Conf struct {  
    Addr     string `json:"addr,omitempty"`  
    Port     string `json:"port"`  
    User     string `json:"user"`  
    Password string `json:"password"`  
}  
  
func main() {  
    conf := Conf{  
    Addr:     "1",  
    Port:     "1",  
    User:     "1",  
    Password: "1",  
}
  
    data, _ := json.Marshal(conf)  
    // 格式化json  
    data_dent, _ := json.MarshalIndent(conf, "", " ")  
    fmt.Println(string(data))  
    fmt.Println(string(data_dent))
    }
  • 设置输出格式

  • func MarshalIndent(v any, prefix, indent string) ([]byte, error)

  • 压缩JSON数据:移除不必要的空格

  • json.Compact(dst *bytes.Buffer, src []byte) error 参数​​:

  • dst:压缩后数据存储的缓冲区

  • src:待压缩的JSON数据

​返回值​​:

  • error:语法错误时返回SyntaxError

​注意事项​​:

  • 会移除所有JSON无效空格和换行符

  • 对无效JSON会报错

  • 不检查JSON内容有效性

  • HTML转义JSON特殊字符

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

参数​​:

  • dst:转义后数据存储的缓冲区

  • src:原始JSON数据

​注意事项​​:

  • 转义字符:<\u003c>\u003e&\u0026

  • 常用来防止XSS攻击

  • 不改变JSON结构

  • 格式化JSON(添加缩进)

  • json.Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error

参数​​:

  • dst:格式化后数据存储的缓冲区

  • src:原始JSON数据

  • prefix:每行前缀

  • indent:缩进字符串

​返回值​​:

  • error:语法错误时返回SyntaxError

​注意事项​​:

  • 对无效JSON会报错

  • 缩进建议使用空格而非制表符

  • 会规范化JSON结构

2 反序列化

  • 将 JSON 数据解析到 Go 结构体或 map 中。

  • json.Unmarshal(data []byte, v interface{}) error

    • v必须是指针类型 注意事项​​:

  • 必须传入结构体指针

  • JSON字段与结构体标签匹配(区分大小写)

  • 多余字段被忽略

  • 缺失字段保留零值

3 流式处理

  • 创建编码器,将数据直接写入 io.Writer(如 HTTP 响应或文件)。

    • json.NewEncoder(w io.Writer) *json.Encoder

  • 将 Go 数据结构(如结构体、切片、映射等)​序列化为 JSON 格式,并直接写入关联的 io.Writer(如文件、HTTP 响应、网络连接等)。

    • func (enc *Encoder) Encode(v any) error

    • v 编码为 JSON 并写入 enc 关联的 io.Writer

  • 创建解码器,从 io.Reader(如 HTTP 请求体或文件)读取并解析 JSON。

    • json.NewDecoder(r io.Reader) *json.Decoder

  • Decoder类型的Decode方法用于从输入流中解析JSON数据并将其解码到指定的Go变量中。

    • func (dec *Decoder) Decode(v any) error

    • dec 是一个指向json.Decoder的指针,该解码器关联了一个输入流(如文件、网络连接等)。

    • v 是目标变量的指针,用于存储解码后的数据。

3.1 json.Decoder类型

用于从输入流(io.Reader)中解码JSON对象。适用于流式读取或处理大型JSON数据。

3.1.1 json.NewDecoder(r io.Reader) *Decoder

功能​​:创建从输入流读取JSON的解码器 ​​参数​​:

  • r:数据源(如os.Filehttp.Request.Body等)

​返回值​​:

  • *Decoder:JSON解码器指针

​注意事项​​:

  • 适用于流式JSON处理

  • Unmarshal更节省内存

  • 解码器会缓存数据,不要直接操作源Reader

3.1.2 (dec *Decoder) Buffered() io.Reader

功能​​:返回解码器缓冲区未读内容 ​​返回值​​:

  • io.Reader:包含缓存数据的读取器

​注意事项​​:

  • 用于跨协议数据传输后读取剩余数据

  • 需在Decode()后调用

  • 读取后缓冲区会被清空

3.1.3 (dec *Decoder) Decode(v any) error

功能​​:解析当前JSON值到结构体 ​​参数​​:

  • v:目标结构体指针

​返回值​​:

  • error:可能的错误:

    • json.SyntaxError:语法错误

    • json.UnmarshalTypeError:类型不匹配

    • io.ErrUnexpectedEOF:意外结束

    • 调用DisallowUnknownFields后出现未知字段

​注意事项​​:

  • 每次调用读取一个JSON值

  • 流结束时返回io.EOF

  • 需确保目标变量可修改(传递指针)

3.1.4 (dec *Decoder) DisallowUnknownFields()

功能​​:开启未知字段错误检查 ​​注意事项​​:

  • 调用后遇到JSON中存在但目标结构没有的字段会报错

  • 适用于严格模式解析

  • 需在Decode()前调用

3.1.5 (dec *Decoder) InputOffset() int64

功能​​:返回当前解码位置的字节偏移量 ​​返回值​​:

  • int64:自流开始的字节偏移量

​注意事项​​:

  • 用于错误定位

  • Decode()Token()之后调用

  • 包含所有已读字节(包括空白)

3.1.6 (dec *Decoder) More() bool

​功能​​:检查是否还有更多元素(在数组/对象内) ​​返回值​​:

  • bool:存在更多元素时返回true

​注意事项​​:

  • 用于遍历数组或对象

  • 在读取[{后使用

  • [/]{/}之间返回true

3.1.7 (dec *Decoder) Token() (Token, error)

功能​​:读取下一个JSON Token ​​返回值​​:

  • Token:可以是:

    • json.Delim:分隔符 [, ], {, }

    • string, float64, bool, nil

  • error:解析错误或io.EOF

​注意事项​​:

  • 用于底层JSON解析

  • Token需在正确的结构上下文中使用

  • 数字默认返回float64,除非使用UseNumber()

3.1.8 (dec *Decoder) UseNumber()

​功能​​:将数字作为json.Number类型解析 ​​注意事项​​:

  • 防止大整数丢失精度

  • 需在首次Token()Decode()前调用

  • json.Number可转为int64/float64/string

3.2 json.Encoder类型

json.Encoder 是 Go 标准库中用于流式 JSON 编码的核心类型,特别适合将 Go 数据结构序列化为 JSON 并写入各种输出流。相比 json.Marshal,它更高效处理大型数据结构和连续输出。

3.2.1 func NewEncoder(w io.Writer) *Encoder

​功能​​:创建 JSON 编码器 ​​参数​​:

  • w io.Writer:JSON 数据目标(文件、网络连接等) ​​返回值​​:

  • *Encoder:初始化好的编码器指针 ​​注意事项​​:

  • 创建后应立即使用

  • 编码器会缓存数据,写入完成后可能需要调用 Flush()(取决于底层 Writer

3.2.2 func (enc *Encoder) Encode(v any) error

​功能​​:将 Go 值编码为 JSON 并写入 ​​参数​​:

  • v any:需要序列化的 Go 值 ​​返回值​​:

  • error:可能的错误:

    • json.UnsupportedTypeError:不支持的类型

    • json.UnsupportedValueError:不支持的值

    • json.MarshalerError:自定义 MarshalJSON 方法错误

    • io 包相关错误(写入失败)

​注意事项​​:

  • 每次调用写入一个完整的 JSON 值

  • 默认会添加换行符(可用 SetIndent 控制)

  • 对通道、函数等不支持类型返回错误

3.2.3 func (enc *Encoder) SetEscapeHTML(on bool)

​功能​​:控制是否转义 HTML 字符 ​​参数​​:

  • on booltrue 开启转义(默认),false 关闭 ​​注意事项​​:

  • 转义字符:<, >, &\u003c, \u003e, \u0026

  • 防止 JSON 被错误解释为 HTML

  • 在输出 HTML 内联 JSON 时建议开启

3.2.4 func (enc *Encoder) SetIndent(prefix, indent string)

​功能​​:设置 JSON 输出缩进格式 ​​参数​​:

  • prefix string:每行前缀

  • indent string:每级缩进字符串 ​​注意事项​​:

  • 通常在首次 Encode() 前调用

  • 会显著增加输出大小

  • 使用空格而非制表符确保跨平台一致性

4 判断字节切片是否为有效JSON

  • json.Valid(data []byte) bool

5 结构体标签

标签选项
说明

json:"-"

忽略该字段

json:"name"

指定 JSON 字段名

json:",omitempty"

字段为空值时忽略

json:",inline"

嵌套结构体的字段平铺到父级 JSON

6 分隔符

6.1 json.Delim类型

该类型用于表示JSON的分隔符,即方括号[]和花括号{}。其底层是一个 rune 类型值。在 json.DecoderToken() 方法中,当遇到 JSON 结构分隔符时会返回该类型值。

6.1.1 func (d Delim) String() string

功能​​:将 JSON 分隔符转换为可读的字符串表示 ​​接收器​​:

  • d Delim:要转换的 JSON 分隔符

​返回值​​:

  • string:分隔符的字符串表示

    • {"{"

    • }"}"

    • ["["

    • ]"]"

注意事项​​:

  • 提供人眼可读的分隔符表示

  • 输出包含引号,便于在日志或调试信息中识别

  • 与直接类型转换相比更易读

7 特殊处理

7.1 json.Number 类型

json.Number 是一个表示 JSON 数字的字符串类型,用于避免大整数或高精度小数在解码时的精度损失。

7.1.1 func (n Number) Float64() (float64, error)

​功能​​:将 JSON 数字转换为 float64​返回值​​:

  • float64:转换后的浮点数

  • error:可能的错误:

    • strconv.ErrSyntax:无法解析为数字

    • strconv.ErrRange:超出 float64 范围

7.1.2 func (n Number) Int64() (int64, error)

​功能​​:将 JSON 数字转换为 int64​返回值​​:

  • int64:转换后的整数

  • error:可能的错误:

    • strconv.ErrSyntax:非整数格式

    • strconv.ErrRange:超出 int64 范围

7.1.3 func (n Number) String() string

​功能​​:返回 JSON 数字的原始字符串表示 ​​返回值​​:

  • string:原始 JSON 数字(未解析)

7.2 使用场景:

  • 处理可能超出 int64 范围的大整数

  • 避免高精度小数的浮点转换误差

  • 需要数字原始格式的场景

7.2.1 json.RawMessage 类型

json.RawMessage 是原始的、未解码的 JSON 字节片段,允许延迟解码或传递原始 JSON。

7.2.2 func (m RawMessage) MarshalJSON() ([]byte, error)

​功能​​:将 RawMessage 作为 JSON 数据直接返回 ​​返回值​​:

  • []byte:原始消息字节

  • error:永不返回错误

7.2.3 func (m *RawMessage) UnmarshalJSON(data []byte) error

​功能​​:将原始 JSON 数据存储到 RawMessage 中 ​​参数​​:

  • data []byte:要存储的原始 JSON ​​返回值​​:

  • error:永不返回错误

8 使用场景:

  • 解组时保留部分 JSON 用于后续处理

  • 构建需要合并多个 JSON 的结构

  • 实现灵活的 JSON 处理管道

9 json.Token 类型

json.Token 是一个表示 JSON 解析过程中令牌的空接口,具体类型包括:

  • json.Delim:分隔符 {, }, [, ]

  • string:字符串值

  • float64:数字值

  • bool:布尔值

  • nil:null 值

使用场景

  • 实现自定义的 JSON 解析器

  • 提取特定部分而不解析整个结构

  • 处理非结构化 JSON 数据

10 自定义序列化/反序列化

在 Go 的 encoding/json 包中,MarshalerUnmarshaler 接口提供了强大的扩展机制,允许开发者完全控制自定义类型的 JSON 序列化和反序列化行为。

10.1 json.Marshaler 接口

功能​​:允许类型自定义其 JSON 编码表示 ​​注意事项​​:

  • 实现此接口后,json.Marshal/Encode 会优先调用此方法

  • 返回的 []byte 必须是有效 JSON

  • 错误处理需明确具体错误类型

  • 优先级高于 TextMarshaler

10.2 json.Unmarshaler 接口

功能​​:允许类型自定义其 JSON 解码行为 ​​注意事项​​:

  • 实现此接口后,json.Unmarshal/Decode 会优先调用此方法

  • 传入的是原始 JSON 字节切片

  • 需要完全处理解码逻辑(包括嵌套结构)

  • 优先级高于 TextUnmarshaler

  • 使用的是必定是指针类型接受者

11 接口反序列化

  • 问题:当想从json文件中反序列化到带有接口类型字段的结构体时,会出现不知道该字段接口底层具体的数据类型

  • 解决:核心思路就是创建一个具有具体类型的 temp 结构体,反序列化到该结构体后再赋值给原结构体

最后更新于