go中数字转json字符串不能直接用json.marshal,因其默认输出原始数值而非带引号字符串;需通过实现json.marshaler接口(如自定义stringnumber类型)或内嵌结构体+重写marshaljson来实现。

Go语言里数字转JSON字符串为什么不能直接用json.Marshal?
因为json.Marshal默认把数字(比如int、float64)序列化成原始数值,不是字符串。你想要"123",它给你123——这在API字段要求字符串类型时会直接报错。
常见场景:对接某些老接口,要求id、amount等字段必须是字符串形式的数字(比如{"id": "1001"}),而你的结构体字段是int64或float64。
- 别试图用
fmt.Sprintf("%d", n)再塞进string字段——这样丢失了类型语义,且无法统一控制序列化行为 - 别用
json.RawMessage硬拼——容易出错,也不利于嵌套结构复用 - 真正可靠的方式是让字段自己决定怎么序列化,即实现
json.Marshaler接口
用json.Number能直接当字符串序列化吗?
不能。这是个常见误解。json.Number本质是string类型别名,它只在json.Unmarshal时有用(避免浮点精度丢失),但json.Marshal遇到json.Number仍会原样输出字符串内容,不加引号——也就是它会被当成原始值,而不是JSON字符串。
比如:
num := json.Number("123")<br>data, _ := json.Marshal(num)<br>// 输出:123(不是 "123")
-
json.Number设计初衷是“无损解析”,不是“强制字符串输出” - 它没有实现
json.Marshaler,所以走的是默认string序列化逻辑(即输出裸字符串,不带双引号) - 想让它变成
"123",必须手动包装一层,比如用指针或自定义类型
正确写法:自定义类型 + MarshalJSON方法
最干净的做法是定义一个包装类型,显式控制序列化行为。例如:
type StringNumber int64<br><br>func (n StringNumber) MarshalJSON() ([]byte, error) {<br> return []byte(`"` + strconv.FormatInt(int64(n), 10) + `"`), nil<br>}
使用时:
type Order struct {<br> ID StringNumber `json:"id"`<br>}<br><br>json.Marshal(Order{ID: 1001}) // 输出:{"id":"1001"}
- 如果要支持小数,把
int64换成float64,用strconv.FormatFloat,注意指定精度(比如64, 10) - 不要用
fmt.Sprintf——它可能引入空格或科学计数法(如1e+06),而strconv系列函数更可控 - 如果字段可能为
nil,建议用指针类型(如*StringNumber),并在MarshalJSON中判断nil返回null
批量处理已有结构体,不想改字段类型怎么办?
可以用内嵌结构体 + 匿名字段 + 自定义MarshalJSON,绕过字段类型修改。例如:
type Order struct {<br> ID int64 `json:"-"`<br> IDStr string `json:"id"`<br>}<br><br>func (o Order) MarshalJSON() ([]byte, error) {<br> type Alias Order // 防止无限递归<br> return json.Marshal(&struct {<br> IDStr string `json:"id"`<br> Alias<br> }{<br> IDStr: strconv.FormatInt(o.ID, 10),<br> Alias: (Alias)(o),<br> })<br>}
- 这种写法适合临时兼容、无法改原始结构体的场景
- 注意
type Alias Order这行必不可少,否则json.Marshal会再次调用Order.MarshalJSON导致栈溢出 - 性能略低于纯字段类型方案,但胜在侵入性小
真正麻烦的不是写法,而是得想清楚:这个“数字当字符串”是全局约定,还是单个字段特例?前者值得封装类型,后者用内嵌方案更轻量。别为了省两行代码,在关键字段上用interface{}或map[string]interface{}硬凑——后期维护成本远高于初期多写几行。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











