["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
yaoyao1128 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 5
类似的还有挪威问题:用 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:29: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 |