V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  BeautifulSoap  ›  全部回复第 32 页 / 共 109 页
回复总数  2178
1 ... 28  29  30  31  32  33  34  35  36  37 ... 109  
2023-09-19 23:54:26 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@rekulas 典型站着说话不腰疼。我写了个例子给你展示所有字段都为指针是什么地狱情况
https://gist.github.com/WonderfulSoap/18a14da135f659d5350f36bdbe439b6a
真的太优雅了,是吧。main2.go 用来模拟在其他包里调用 Data2 数据的情况。悄悄跟你说 Calculate() 里已经塞入了两个 bug 了哦? data.I 和 data.Obj1.I 是可 null 字段段,所以不能直接取值。那么问题来了,如此高的心智负担这么多指针倒来倒去,你怎么确保你每次取值都取得万无一失?
2023-09-19 23:15:49 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@houshuu
> 如果"需要对传入的数据做最低限度的确认", 那么就应该用指针. 因为这句话的背后已经说明了有可能为 null

你好,你这已经是我针对不同人提出的同一个问题的第三次回复了。定义成指针是没有可行性的做法。理由很简单,作为后端我必须不相信前端,所以我要考虑 DTO 的所有字段都有可能被前端瞎传入 null 的情况。
如果采用指针的话,这意味着我一切 struct 中每一个字段都必须定义成指针。这根本不现实对吧?整个项目 DTO 中所有字段全是指针用起来一定很酸爽对吧。再一个,实际项目中 API 并不是所有字段都禁 null ,个别字段是允许 null 的,所有一切字段都定义成指针的话,请问你能轻松分辨出这一堆指针类型的字段中,哪些是允许 null 哪些是禁止 null 的?更要命的是,使用字段值的时候到底哪个字段要加*,哪个字段要判 nil ?

> 如果连测试都不需要

不好意思,不是没有测试而是测试没有覆盖到。你如果认为所有项目只存在完全没测试和所有测试条件都覆盖到的两种极端的话那就太理想了

> 不是自己的锅别接, 别人再怎么说也改变不了这个不是后端的问题

不是的,锅的确不是自己的我也不会接,但是因此产生的生产事故和因为事故调查、恢复加的班是实打实(你不可能叫前端过来给你查后端 l 日志,抽取数据回复被破坏的生产环境)
2023-09-19 23:00:53 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@lshang 你说的非常对,你说的这个情况其实就是我顶楼给的几个例子中之一

解析下面的 json 都会成功,解析结果就是所有没有填的字段全为空值

{"a": "a"}
{}
{"obj": {}}
2023-09-19 22:57:40 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@rekulas 我不知道是自己说明能力太差还是你没法理解,我举例 python 、php 、js 只是想说他们都会将 json 中的 null 解析成对应语言中的 None/null 。这点你能明白吗?然后在 Go 语言里,与 json 的 null 最接近的概念也就只有 nil 了,你同不同意?所以将 null 的解析为 nil → 而非指针类型无法赋值 nil 从而会引发解析错误难道不是非常自然的想法?为什么你会认为这是个校验的问题呢?

而且如果要较真的话,我们再来深入思考一个问题,什么才叫校验?你说 null 解析成 nil 赋值给非指针字段是校验问题,那么解析如下 json {"a":"hello"}到 这个结构体 struct { A int} 是不是也应该归类为校验问题? 在这里 A 是 int 类型,但是传入了字符串,两者的类型不对的检测是不是也应该交给校验?按照你的说法,解析 { "a": "hello"} 的结果就应该和{"a": null} 一样都解析成 0 ,然后交给校验来处理是不是?
2023-09-19 22:30:10 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@gogogo1203 #33 “前端来的 json 用一个 struct, 校验完” 其实问题就出现在怎么校验这一步上啊。null 会被解析成对应字段类型的空值,也意味着根本没有手段去校验 json 传入的是不是 null 。问题就出现在这一步了。我顶楼给的那几个涉及到 null 的例子就是最好写照
2023-09-19 22:25:25 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@gogogo1203 这方法使用 DisallowUnknownFields 能解决问题 1 ,但问题 2 没办法解决
2023-09-19 22:14:33 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@delacey 我顶楼也说了,直到踩到坑之前我都一直以为 json 包替我完成了对 null 的校验啊。你要想,json 包做解析的时候吧 string 解析到 int 类型字段会报错,那么谁会想到把 null 解析到非指针字段就不会报错了呢?

> 都是不出事就注意不到的问题。尤其非指针类型字段,我下意识认为遇到 null 是会直接报错的,结果直接是当作不存在(undefined)来处理。。。
2023-09-19 22:11:31 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@houshuu 你可能都没看懂我这贴的意思到底是什么。我只是举例,出的事故不是订单相关。

后端不应该信任前端/外部端口传入的数据,所以后端需要对传入的数据做最低限度的确认,如果不符合预期和要求就要报错。请问这点你同不同意?
这次问题就出在“对传入数据做最低限度的确认”上,API 接口约定不能传 null ,但是外部接口传了 null ,在 json 解析的时候自然而然会认为要给非指针赋值 nil ,json 包肯定会报错,但实际上它解析成空值不报错,而空值 0 是业务允许的,从而引发了生产事故

自然,传了 null 的确是前端/外部接口的锅,但除了生产事故加班 log 调查、数据查找、确立回复数据库数据都是后端/运维的工作。到时候如果来一句“虽然 xxx ,但后端连 null 都不检查的吗”就问你怎么应对。
2023-09-19 21:48:46 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@Maboroshii
@kumoocat
“Go 不用指针就代表不能为 null”
“那你知不知道,golang 里面,struct 只有 0 值没有 null 值呢”

你们说的对啊,Go 里一个类型不是指针代表这个类型不能赋值 nil ,json 解析的时候遇到 null 意思就是要把 nil 赋值给非指针,直接报错不是再正常不过的想法吗?


“你也知道,你列举的这些语言,对象是可为 null 的”
这里面和 go 最相近的是 Go ,因为 kotlin 和 go 一样类型分可空/非可空(对应到 go 近似看成指针/非指针)。当尝试将 null 解析到非可空字段时,kotlin 是可以报错的
2023-09-19 21:40:04 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@tairan2006 要改成指针的可不止匿名类,匿名类里的 AA 、BB ,外面的 A 和 B 也都得要改成指针哦。然后就出现了我 2L 说的问题,为了解决 null 判定这一个问题,整个 struct 全部字段都定义成指针,实在过于得不偿失了。

@Maboroshii 其实问题不在“已知字段会为 null”,而是 API 文档已经明确约定了些字段全都不能为 null ,但外部接口/前端就硬是给你传了 null (不要问为什么,后端永远不能相信前端传给你的数据是什么牛鬼蛇神,实际上这次出事就是因为约定了非 null 的字段外部接口给传了 null 。)
2023-09-19 21:31:08 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@haoxue 多谢我试试
@tuxz 正常来说一个实际的项目中,要从 json 解析出 struct 的数量是几十上百个的。。。一个个实现不太现实,写通用方法塞进去倒也是个办法,但是也容易出纰漏


@ye4tar
@RedisMasterNode
是的,我思前想后可能也就只能自己魔改官方 json 包了。不过倒也用不着 validator ,直接在解析 json 的时候,如果目标字段为非指针类型,遇到 null 就直接报错可能会更直接的。一直不太想自己魔改主要是总感觉自己写的东西是重复造轮子,,,,
2023-09-19 21:22:45 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@rekulas 如果你是个合格的程序员并且经验丰富接触的语言也不只有一种的话,那么你会清楚一般来说语言解析遇到 null 的话,都会尽量将其解析为对应语言中的空指针/null/None 一类。比如 python 把 null 解析为 None, js 、php 、java (大部分 json 包)会把 null 解析为 null 。而对于 kotlin 这种明确区分了空值非空值的语言,将 null 解析为非空类型的字段会直接报错。

话题绕回来,对于 json 来说 null 存在是合理的,但是将 null 解析为非指针的时候不报错解析为默认空值是不合理的。请问你如何区分 {"a":null} {"a":0} ?而且落地到实际项目中,假设一个 api 接口所有字段都是禁止传 null 的,但是前端/外部接口就硬是因为 bug 之类的给你传了个 null ,请问你认为是直接报错拒绝请求比较好呢,还是直接解析成对应类型空值去处理业务从而引发严重事故好?
2023-09-19 20:51:58 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@knightdf
@dobelee
@pkoukk
关于 validation 这件事,你们真的应该亲自试试,就会发现这根本不是 validation 能解决的问题。
null 会被解析为默认空值,如 int 字段传入 null 会被解析为 0 ,即便用 validator 这个包做 validation 检测也只能检测字段是不是 0 。但在实际业务中 int 值字段为 0 基本都是正常值,不应该被报错


@RedisMasterNode
你理解错 9L 的意思了,你提供的这段代码其实是有问题的。比如你尝试解析下 `{"name": "john", "age": 0}` 是会报错的(有的地区是有 0 岁这个概念的哦),单纯在解析后用 validator 是没法区分传入的到底是 0 岁还是 null 的
2023-09-19 18:01:24 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@ye4tar 试了下没效果。json 包其实不不支持 notnull, required 标签的
2023-09-19 16:19:26 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@fgwmlhdkkkw json.Unmarshal() 会把 null 解析成对应类型的空值,比如 int 的话就是 0 。validation 只能判断是不是 0 不能判断是不是 null ,派不上用场
2023-09-19 15:37:14 +08:00
回复了 BeautifulSoap 创建的主题 Go 编程语言 踩到 Go 的 json 解析坑了,如何才能严格解析 json?
@zhs227 可能不太现实,因为通过定义成指针来满足第二点需求的话,意味着结构体全部字段都必须定义成指针。如果字段非常多(几十上上百个)一个个判断代码量和工作量非常大增减字段容易出纰漏(最终要上反射)。而且所有字段定义成指针的话,使用起来会相当难受
2023-09-19 10:25:30 +08:00
回复了 KOMA1NIUJUNSHENG 创建的主题 问与答 哪些人会买 iPhone 的 plus 系列
数字系列和 pro 的屏幕太小了,我要买只会考虑 plus 或 pro max
2023-09-18 15:46:49 +08:00
回复了 cloud2000 创建的主题 问与答 寻找 Chrome 插件:让 GPT 读取并解析网页内容后进行提问
edge 不是自带吗
虽然我很能喝酒,过年和老家那些老头灌白酒也行,但日本呆久了,梅酒,各种口味的沙瓦,高球鸡尾酒之类的喝多了,你让我闲得没事去喝四五十度的酱香白酒,我怕不是脑子抽了
白酒这种联动只能说是死前挣扎,再过十几年白酒越来越不行肯是趋势
1 ... 28  29  30  31  32  33  34  35  36  37 ... 109  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4365 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 26ms · UTC 04:06 · PVG 12:06 · LAX 20:06 · JFK 23:06
Developed with CodeLauncher
♥ Do have faith in what you're doing.