被 go 语言的 json.Marshal 恶心到了

109 天前
 qW7bo2FbzbC0

我的需求是,输入 sql ,返回序列化后的 json 结果。

在 python 中,官方库就可以返回[{'col1': 1, 'col2': '2', 'col3': true}....] 这种带类型的 json 结果。

在 go 中如果已知 sql 返回的列数和列类型,也可以构造一个 struct 进行数据映射,然后用json.Marshal转为 json 。

如果 sql 返回的列数和行类型未知,就很难受了,在 go/mysql 的官方 wiki 案例 中对于匿名的结果,使用了 interface 或者 sql.RawBytes ,但这两种替代方式在json.Marshal后都变成了 base64 encode 后的 string ,既丢失了类型也变异了结果( https://stackoverflow.com/questions/32501784/the-sqlx-library-gives-weird-base64-encoded-looking-results)

请问各位在实际业务中遇到这个问题是怎么处理的?

在其他语言中很自然的 object 序列化为原类型,在 go 的 json.Marshal 中怎么就全变成 string 了

11707 次点击
所在节点    Go 编程语言
131 条回复
yrzs
109 天前
FrankFang128
109 天前
没遇到过,没看懂
3img
109 天前
如果是不知道指针的类型,可以用反射啊
dzdh
109 天前
我翻译一下。

up 想要 go 实现 php 的 json_encode(PDO->fethcAll()) 不定义 struct
NessajCN
109 天前
首先 Marshal 是序列化,Unmarshal 是反序列化, 也就是从 byte 到 go struct 应该用 Unmarshal
其次,对于未知的返回类型一般不 Unmarshal , 直接从 interface 里取键值,go 自带返回 ok 判断是否有这个 key
譬如
```go
type SqlResult map[string]interface{}
var res SqlResult
if col1,ok := res["col1"].(int32); ok {
//...
}
```
povsister
109 天前
你适合用 python
sagaxu
109 天前
根据 ColumnType 判断一下字段类型,自己写个转换,把[]byte 和[]uint8 都转成 string
laikick
109 天前
你适合用 PHP
zxdstyle
109 天前
这不是 go 和 python 的区别,是强类型语言与弱类型语言的区别
Goooooos
109 天前
@zxdstyle 其实 python 也是强类型语言
sagaxu
109 天前
@laikick 除了 PHP ,Python 和 Java 也行,这件事情上,唯独 Go 比较大道至简
james122333
109 天前
你可以用 map[string]any 或 json.RawMessage
james122333
109 天前
map[string]any, []any...族繁不及备载
Nazz
109 天前
要修改下结构体定义, 例如把 []uint8 换成 []uint16
james122333
109 天前
看 col 举例应该是[]map[string]any
ChrisFreeMan
109 天前
OP 赶紧跑吧你完了
luhengyuorang
109 天前
最开始用 py 或者 php 的来写 go ,很容易有代入感,经常看到别人把 go 写成 php
dcalsky
109 天前
收收 python 、js 、php 味。go 的正规业务里,都要得先定义 struct ,不到万不得已不用 map[string]any
liaohongxing
109 天前
总结不适应强类型
rekulas
109 天前
go 真冤 完全没看懂这跟 go 有什么关系

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1057942

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX