Golang JSON RawMessage

在 Go 的 encoding/json 包中,json.RawMessage 是一个很实用的类型。它本质上是 []byte,用于保存一段未经解析的 JSON 数据,让程序可以延迟决定如何解析

例如接口返回的数据中,data 字段可能对应不同结构:

type Response struct {
    Code int             `json:"code"`
    Data json.RawMessage `json:"data"`
}

第一次 json.Unmarshal 时,Data 不会被解析成 map[string]any,而是直接保存原始 JSON。根据 Code 或其他字段确定具体类型后,再进行第二次解析:

var user User
if err := json.Unmarshal(resp.Data, &user); err != nil {
    return err
}

这种方式特别适合多态 JSON、动态字段、消息路由和兼容不同版本的数据结构

any 的区别

如果使用 any 接收 JSON,就相当于把内容当作 map[string]any 解析,其中数字解析为 float64,导致类型信息丢失。

json.RawMessage 则保留 JSON 原文,可以在真正需要时再决定目标类型,也避免了不必要的解析。

type Response struct {
    Type string `json:"type"`
    Data any    `json:"data"`
}

{
  "type": "user",
  "data": {
    "id": 123,
    "name": "Woody"
  }
}

// map[string]any{
//     "id":   float64(123),
//     "name": "Woody",
// }
如果你有魔法,你可以看到一个评论框~