V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  BeautifulSoap  ›  全部回复第 24 页 / 共 101 页
回复总数  2016
1 ... 20  21  22  23  24  25  26  27  28  29 ... 101  
@lshang 你说的非常对,你说的这个情况其实就是我顶楼给的几个例子中之一

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

{"a": "a"}
{}
{"obj": {}}
@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 ,然后交给校验来处理是不是?
@gogogo1203 #33 “前端来的 json 用一个 struct, 校验完” 其实问题就出现在怎么校验这一步上啊。null 会被解析成对应字段类型的空值,也意味着根本没有手段去校验 json 传入的是不是 null 。问题就出现在这一步了。我顶楼给的那几个涉及到 null 的例子就是最好写照
@gogogo1203 这方法使用 DisallowUnknownFields 能解决问题 1 ,但问题 2 没办法解决
@delacey 我顶楼也说了,直到踩到坑之前我都一直以为 json 包替我完成了对 null 的校验啊。你要想,json 包做解析的时候吧 string 解析到 int 类型字段会报错,那么谁会想到把 null 解析到非指针字段就不会报错了呢?

> 都是不出事就注意不到的问题。尤其非指针类型字段,我下意识认为遇到 null 是会直接报错的,结果直接是当作不存在(undefined)来处理。。。
@houshuu 你可能都没看懂我这贴的意思到底是什么。我只是举例,出的事故不是订单相关。

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

自然,传了 null 的确是前端/外部接口的锅,但除了生产事故加班 log 调查、数据查找、确立回复数据库数据都是后端/运维的工作。到时候如果来一句“虽然 xxx ,但后端连 null 都不检查的吗”就问你怎么应对。
@Maboroshii
@kumoocat
“Go 不用指针就代表不能为 null”
“那你知不知道,golang 里面,struct 只有 0 值没有 null 值呢”

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


“你也知道,你列举的这些语言,对象是可为 null 的”
这里面和 go 最相近的是 Go ,因为 kotlin 和 go 一样类型分可空/非可空(对应到 go 近似看成指针/非指针)。当尝试将 null 解析到非可空字段时,kotlin 是可以报错的
@tairan2006 要改成指针的可不止匿名类,匿名类里的 AA 、BB ,外面的 A 和 B 也都得要改成指针哦。然后就出现了我 2L 说的问题,为了解决 null 判定这一个问题,整个 struct 全部字段都定义成指针,实在过于得不偿失了。

@Maboroshii 其实问题不在“已知字段会为 null”,而是 API 文档已经明确约定了些字段全都不能为 null ,但外部接口/前端就硬是给你传了 null (不要问为什么,后端永远不能相信前端传给你的数据是什么牛鬼蛇神,实际上这次出事就是因为约定了非 null 的字段外部接口给传了 null 。)
@haoxue 多谢我试试
@tuxz 正常来说一个实际的项目中,要从 json 解析出 struct 的数量是几十上百个的。。。一个个实现不太现实,写通用方法塞进去倒也是个办法,但是也容易出纰漏


@ye4tar
@RedisMasterNode
是的,我思前想后可能也就只能自己魔改官方 json 包了。不过倒也用不着 validator ,直接在解析 json 的时候,如果目标字段为非指针类型,遇到 null 就直接报错可能会更直接的。一直不太想自己魔改主要是总感觉自己写的东西是重复造轮子,,,,
@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 ,请问你认为是直接报错拒绝请求比较好呢,还是直接解析成对应类型空值去处理业务从而引发严重事故好?
@knightdf
@dobelee
@pkoukk
关于 validation 这件事,你们真的应该亲自试试,就会发现这根本不是 validation 能解决的问题。
null 会被解析为默认空值,如 int 字段传入 null 会被解析为 0 ,即便用 validator 这个包做 validation 检测也只能检测字段是不是 0 。但在实际业务中 int 值字段为 0 基本都是正常值,不应该被报错


@RedisMasterNode
你理解错 9L 的意思了,你提供的这段代码其实是有问题的。比如你尝试解析下 `{"name": "john", "age": 0}` 是会报错的(有的地区是有 0 岁这个概念的哦),单纯在解析后用 validator 是没法区分传入的到底是 0 岁还是 null 的
@ye4tar 试了下没效果。json 包其实不不支持 notnull, required 标签的
@fgwmlhdkkkw json.Unmarshal() 会把 null 解析成对应类型的空值,比如 int 的话就是 0 。validation 只能判断是不是 0 不能判断是不是 null ,派不上用场
@zhs227 可能不太现实,因为通过定义成指针来满足第二点需求的话,意味着结构体全部字段都必须定义成指针。如果字段非常多(几十上上百个)一个个判断代码量和工作量非常大增减字段容易出纰漏(最终要上反射)。而且所有字段定义成指针的话,使用起来会相当难受
281 天前
回复了 KOMA1NIUJUNSHENG 创建的主题 问与答 哪些人会买 iPhone 的 plus 系列
数字系列和 pro 的屏幕太小了,我要买只会考虑 plus 或 pro max
edge 不是自带吗
虽然我很能喝酒,过年和老家那些老头灌白酒也行,但日本呆久了,梅酒,各种口味的沙瓦,高球鸡尾酒之类的喝多了,你让我闲得没事去喝四五十度的酱香白酒,我怕不是脑子抽了
白酒这种联动只能说是死前挣扎,再过十几年白酒越来越不行肯是趋势
?这需求 jellyfin 不是完美满足吗,你建媒体库的时候类型选错了,别选电影
@brader samba 服务器任意一个第三方文件管理器都支持的东西。mixplorer (不光有 samba ,ftp/sftp/http/webdav 服务器都有),x-plorer ,es 文件浏览器之类的基本算是标配了
1 ... 20  21  22  23  24  25  26  27  28  29 ... 101  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3665 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 44ms · UTC 05:12 · PVG 13:12 · LAX 22:12 · JFK 01:12
Developed with CodeLauncher
♥ Do have faith in what you're doing.