["01", "02", "03", "04", "05", "06", "07", "08", "09"]
这个数组转换为 YAML:
- '01' - '02' - '03' - '04' - '05' - '06' - '07' - 08 - 09
这样的行为是符合标准的。
但是,如果你转换回来:
["01", "02", "03", "04", "05", "06", "07", 8, 9]
大家可以试试自己常用的程序有没有这样的问题。
Reference:
这个问题找到一个解决办法了,可以开启 yaml tag 来强制标注类型。
>>> print(yaml.dump(["01", "02", "03", "04", "05", "06", "07", "08", "09"], canOnical=True)) --- !!seq [ !!str "01", !!str "02", !!str "03", !!str "04", !!str "05", !!str "06", !!str "07", !!str "08", !!str "09", ] >>> print(yaml.dump(["01", "02", "03", "04", "05", "06", "07", "08", "09"])) - '01' - '02' - '03' - '04' - '05' - '06' - '07' - 08 - 09
我觉得有一个值得思考的地方,就是“遵守标准”就一定对吗?当“遵守标准”和“最大化兼容性”必须进行取舍的时候,我们应该选择哪一个呢?
![]() | 1 qwerthhusn 2022-01-04 14:13:11 +08:00 目测是库把其当成 8 进制数字了 |
![]() | 2 yaoyaomoe 2022-01-04 14:17:50 +08:00 via iPhone |
![]() | 3 baobao1270 OP @yaoyao1128 问题就在这里呀,你的实现要保证 load 和 dump 一致啊 |
4 kingxiangqi 2022-01-04 16:01:34 +08:00 离谱。字符串不应该始终保持原样吗?为什么会被当做数字处理? |
![]() | 6 ysc3839 2022-01-04 16:30:42 +08:00 yaml 本来设计就不是让程序生成的吧?设计是让人手写,程序读取,因此弱化了类型系统,理论上来说 yaml 只有文本的,没有整数啥的。你举的例子是因为程序自动进行了类型转换。 |
![]() | 8 ysc3839 2022-01-04 17:32:31 +08:00 @makelove 我说的有问题,是指不适合楼主所说的“保证 load 和 dump 一致”这种情况。相反,JSON 是有库可以实现保留大部分格式的,包括注释也能保留。 |
![]() | 9 mcfog 2022-01-04 17:41:34 +08:00 ![]() 类似的还有挪威问题:用 yaml 写国家码 US CN JP KR 不亦乐乎直到有一天遇到了挪威… https://hitchdev.com/strictyaml/why/implicit-typing-removed/ |
![]() | 10 cweijan 2022-01-04 17:44:41 +08:00 这是你的解析库有问题, 和 yaml 标准有什么关系 |
![]() | 11 codehz 2022-01-04 17:45:26 +08:00 via Android 类似的问题多了去了 https://github.com/cblp/yaml-sucks |
![]() | 12 mcfog 2022-01-04 17:47:25 +08:00 个人观点,标准过于复杂能力过多导致多数解析器都有各种问题甚至安全漏洞,这是 yaml 标准不够好的地方,不能完全怪实现。在合适的时候,比起花时间找更好的实现,我会选择换更简单从而更不容易出错的标准,例如 json, toml 等 |
![]() | 13 baobao1270 OP @ragnaroks 你确定是正常的吗?我这里显示是这样的 'number-list': [ '01', '02', '03', '04', '05', '06', '07', 8, 9, '10', '11' ] 可能你没有理解我的意思,符合标准的解析器应该把它解析为 'number-list': [ '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11' ] 而且巧了我就是在 Minecraft 里碰到这个问题的。 @cweijan 问题就在这里,libyaml 、js-yaml 、pyyaml 等库都认为把 "08" 转换成 08 是符合标准的,但是把 08 转换成 int 8 也是符合标准的。他们都选择了“遵从标准实现”而不是“最大化兼容性”。 @ysc3839 #8 @mcfog 问题就是在这里,你没法控制不是你写的代码,人家要用 YAML 还要多次 load 和 dump 你也没法改啊,比如 Minecraft 的 mod 实现的“导出配置”的功能。 |
![]() | 14 ragnaroks 2022-01-05 09:03:49 +08:00 @baobao1270 如果原本是数值 08 解析为 8 没问题,如果是字符串"08"解析为"08"也没问题;如果 "08" 被解析为 8 那才是问题 |
![]() | 15 ragnaroks 2022-01-05 09:06:12 +08:00 写了个 bukkit 插件测试 List<int> list1=new List<int>{2,4,6,8,10}; List<string> list2=new List<string>{"2","4","6","8","10"}; plugin.yml: list1 - 2 - 4 - 6 - 8 - 10 list2 - "2" - "4" - "6" - "8" - "10" |
![]() | 16 SmiteChow 2022-01-05 10:10:21 +08:00 不用思考和怀疑,遵循标准这个行为一定是正确的,标准用于规范生产,降低协作成本,最后才是提高效率。 |
![]() | 17 baobao1270 OP @ragnaroks “如果原本是数值 08 解析为 8 没问题”这句话是有问题的,08 应该转化为"08"而不是 8 “如果 "08" 被解析为 8 那才是问题” 其实这就是问题本身YAML 认为 08 和 "08" 是同一个东西 |
18 2i2Re2PLMaDnghL 2022-01-05 12:9:30 +08:00 YAML 标准 1.2 中将八进制数的表示方式改为 0o777 这样(小写字母 o ) |
19 2i2Re2PLMaDnghL 2022-01-05 13:46:59 +08:00 我以各种关键词搜索了一下标准,发现标准中似乎没有规定以 `0` 开头的数字,比如 ``` 08 ``` (也包括 09 )的实际含义。(可能是我看漏了) |
![]() | 20 rv54ntjwfm3ug8 2022-04-17 07:28:19 +08:00 这个问题更常出现在 port mapping 里 例如 https://stackoverflow.com/questions/58810789/quotes-on-docker-compose-yml-ports-make-any-difference |