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

201 天前
 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 了

13262 次点击
所在节点    Go 编程语言
131 条回复
ly020044
200 天前
看一下 ```json.Marshaler``` 这个接口
ly020044
200 天前
看一下 json.Marshaler 这个接口
hekkowoerld
200 天前
与其说是其他人在这攻击楼主不会用,倒是楼主积极探索的态度值得鼓励,本人也觉得这个用法很蹩脚。
jc89898
200 天前
啥也不是
lesismal
200 天前
@zzhaolei
@XyIsMy

一是: orm 本身是二次加工生成代码,不是直接 sql 语句不直观。日志 level 的方式打印出来的在复杂 orm 使用过程中、可能随着输入参数不一样可能做不到线上所有情况的 sql 范式覆盖,而且 orm 还有一些隐式的东西不是程序员自己设定的,比如一些 orm 库处理数据库的 null 值还是什么来着, 需要额外去绕过,具体哪个库哪些坑我记不清了,各位可以自己搜索引擎搜下或者官方 issue list 去看,我因为抵制 orm 所以对 orm 也没深入研究
二是,这也是更重要的一点,orm 培养了很多程序员的使用习惯、抛弃了 raw sql ,我见过的绝大多数初级中级同行、以及多数所谓的高级开发(至少八年十年以上经验),都是只要 orm 能实现功能就搞上去了,性能神马的都是事后线上出了问题再去搞。比如上面说的日志 level 打印出 sql 来, 但很多人习惯了 orm 开发方式这种思维,即使打印出来也不会去关注 sql 性能相关. 咱国内人口基数大, 中等规模的公司就可能经常遇到数据量较大的量级, 在做这类项目的时候、尤其是 OLAP 涉及大量统计汇总操作的,一个没留神就被 orm 选手搞性能事故了. 跟这类兄弟共事, 为了避免这些, 研发流程上已经做了很多把关, 但仍瑟瑟发抖.
lesismal
200 天前
@zzhaolei #93 不是回复我的,我之前没看到,可以看下我 #105 的,也可以看些其他帖子,比如 Xargin 的:
https://github.com/cch123/blog_comment/issues/254
还有一些其他帖子例如:
https://juejin.cn/post/7174222105788514334
https://studygolang.com/articles/23459

你可以看到一些 orm 、非 orm 优劣的对比包括 gorm 或者 xorm 的一些坑你都可以去搜下看看。单就性能风险这一点上,高阶一点的开发者基本上是达成一致的,orm 自己的泛型导致的性能损失都是小损失,最大的风险就是我在#105 说的,或者 Xargin 文章里讲的。只有没怎么经手过大项目的才会对 orm 这个坑人风险的说法这么不屑一顾

“我就是好奇,这些人张嘴闭嘴就是 ORM 有不确定性,到底有什么不确定性,自己测试过?还是踩过坑?还是说嘴一张一闭反正我不管,ORM 就是有性能问题?”

这个观点是你在自己现阶段水平下得出的结论,但当你以后技术进阶了很可能会自己推翻自己这个观点。如果对技术有追求,可以多试试大项目的工作。如果现在的工作项目量级对性能没那么大要求且钱多那就无所谓了,能挣钱就行,技术都是浮云
ryalu
200 天前
@XyIsMy #91 上家公司的头头与他的思想恰恰相反,因为团队里难免技术参差不齐,很难避免有人写出垃圾 sql 导致 sql 注入的风险,反而会鼓励我们用 orm..... 上手简单,很难写出危险 sql
XyIsMy
200 天前
@lesismal 风险和习惯这个确实是存在的,避免不了。那怕定好流程规范,开发人员也一样会产出风险。这层只能靠不断的灌输思想和从架构上避免风险。

但也理解你的想法了,想尽可能使用原生 sql ,一个是降低 orm 隐性的 bug (不一定有,但想尽可能避免),另外一层,在出现性能问题时,可以快速定位问题( orm 在定位 sql 这层是办不到的)
pangdundun996
200 天前
在 python 中,官方库就可以返回[{'col1': 1, 'col2': '2', 'col3': true}....] 这种带类型的 json 结果。
------
谁能解释一下啥叫带类型的 json 吗?
XyIsMy
200 天前
@ryalu 哈哈哈哈, 这个没有绝对的对错, 每个团队的习惯和方案都是经过很多业务问题沉淀出来的。下面简单的举例一下,并不严谨和也不全面。
比如
1.小型业务,团队头头会更关注,csrf ,xss ,sql 注入等等攻击风险,因为还跑不到数据库性能层
2.中型业务,团队头头会更关注,csrf ,xss ,sql 注入 + 应用 sql 调优
3.大型业务,团队头头会更关注,csrf ,xss ,sql 注入 + 应用 sql 调优 + 数据库实例调优 ,数据安全 等等
qW7bo2FbzbC0
200 天前
另外 sqlx 最新版本也修复了 map[string]interface{}返回 base64 encode 字符的问题
ukissme
200 天前
其实还好,楼主少见多怪,自己菜
lambdaq
200 天前
你们俩打一架

/t/1056990 现在极其厌恶弱类型语言,弱类型就不适合中国的职场环境
/t/1057942 被 go 语言的 json.Marshal 恶心到了
qW7bo2FbzbC0
200 天前
@all mysql driver 还有这个问题,int 正常,但是 string 还是 base64 encode 字符串,json.RawMessage 也不顶用。sqlite3 的驱动是正常的
qW7bo2FbzbC0
200 天前
@lambdaq 和强弱类型没有关系,驱动底层逻辑问题
lambdaq
200 天前
@qW7bo2FbzbC0 如果说关系的话,你举的这个例子,属于强类型语言里禁术。一个 list/array 里最好类型都是整整齐齐统一的。也就是那个帖子里所说的 “现在好了,到处都是字典 + 字符串取值,这个字符串 key 还是尼玛自己定义的,和 idl 都对不上,得自己去代码里面到处翻找,看看到底是哪个接口返回的。”

所以我觉得你们俩要不打一架。
baolongqishi
200 天前
zmqiang
199 天前
这个问题遇到过,这个肯定和 go 的 json 库无关,最多怪到数据库上的 driver 上,没有做好数据类型的映射
debugman66
199 天前
@XyIsMy 有点好奇是什么样的大公司,连个慢 sql 监控的工具都没有,还需要手动去看代码定位
XyIsMy
199 天前
@debugman66 我也没表达大公司需要手动定位慢 sql 的意思啊。这个说法哪来的哦

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

https://tanronggui.xyz/t/1057942

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

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

© 2021 V2EX