
本文详解如何在 go 编写的 mysql rest api 中准确映射和序列化数据库中的 json 类型字段,避免将嵌套 json 错误转义为字符串,确保客户端接收到结构化、可直接解析的 json 对象。
本文详解如何在 go 编写的 mysql rest api 中准确映射和序列化数据库中的 json 类型字段,避免将嵌套 json 错误转义为字符串,确保客户端接收到结构化、可直接解析的 json 对象。
在 Go 中通过 database/sql 读取 MySQL 的 JSON 类型列时,驱动(如 go-sql-driver/mysql)默认将其作为 []byte 或 string 返回,而非原生 JSON 结构。若直接映射为 string 字段(如 Data string),Go 的 json 包会将其双重编码:先将原始 JSON 字符串(如 {"field":"nowork"})当作普通字符串字面量,再序列化为带转义的 JSON 字符串("{\"field\":\"nowork\"}"),导致前端无法直接使用。
正确的做法是让 Data 字段保持为 可被 json.Marshal/json.Unmarshal 直接处理的类型。推荐两种生产级方案:
✅ 方案一:使用 json.RawMessage(标准库,零依赖)
type Map struct {
ID int `json:"id"`
Data json.RawMessage `json:"data"` // 关键:保留原始 JSON 字节流,不预解析
Created time.Time `json:"created"`
UserID int `json:"user_id"`
}
查询时直接扫描为 []byte(MySQL 驱动对 JSON 列返回 []byte):
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
func GetMap(id int) (Map, error) {
var m Map
err := _getMap.QueryRow(id).Scan(&m.ID, &m.Data, &m.UserID, &m.Created)
if err != nil {
return Map{}, err
}
return m, nil
}
json.RawMessage 会原样嵌入 JSON 数据,在最终 json.Encoder.Encode() 时直接输出合法 JSON 对象,无转义。
✅ 方案二:使用 map[string]interface{} 或自定义结构体(需明确 schema)
若 JSON 内容结构固定,可定义具体结构体提升类型安全:
type MapData struct {
Field string `json:"field"`
Count int `json:"count"`
}
type Map struct {
ID int `json:"id"`
Data MapData `json:"data"` // 自动解码 + 编码
Created time.Time `json:"created"`
UserID int `json:"user_id"`
}
// 查询时需手动解析
func GetMap(id int) (Map, error) {
var m Map
var dataBytes []byte
err := _getMap.QueryRow(id).Scan(&m.ID, &dataBytes, &m.UserID, &m.Created)
if err != nil {
return Map{}, err
}
if err := json.Unmarshal(dataBytes, &m.Data); err != nil {
return Map{}, err
}
return m, nil
}
⚠️ 注意事项
- 避免 string 类型映射 JSON 列:这是导致双重转义的根本原因。
- 慎用第三方 JSON 库(如 jason):虽然可行,但引入额外依赖且不如标准库 json.RawMessage 简洁高效;jason 返回的对象需额外实现 json.Marshaler 接口才能被 json.Encoder 正确处理,原文示例实际隐含了该实现或存在简化。
-
空值处理:MySQL JSON 列允许 NULL,扫描到 sql.NullString 或 *[]byte 更健壮:
var dataBytes *[]byte err := row.Scan(&id, &dataBytes, &userId, &created) if dataBytes == nil { m.Data = json.RawMessage("null") } else { m.Data = json.RawMessage(*dataBytes) }
综上,优先选用 json.RawMessage —— 它是 Go 标准库专为此类场景设计的类型,零开销、高兼容、无需额外依赖,完美解决 MySQL JSON 字段在 REST API 中的透传问题。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










