提问人:Corvus 提问时间:11/17/2023 最后编辑:Corvus 更新时间:11/18/2023 访问量:89
有没有办法让serde_json正确/不正确地处理 NaN、Inf 和 -Inf(IEEE 754 特殊)?
Is there a way to make serde_json handle NaN, Inf and -Inf properly/improperly (IEEE 754 Specials)?
问:
官方的 JSON 规范不支持 IEEE 754,而是有自己的 null(不是“null”)或普通数字的约定。
在许多语言和用例中,人们会忽略这一点,并偏离规范以支持IEEE754浮点数。例如,在 python 中
>>> json.dumps(dict(a = np.inf, b = -np.inf, c = np.nan), allow_nan=True)
'{"a": Infinity, "b": -Infinity, "c": NaN}'
在本例中,allow_nan默认为 True。
同样,在 C# 中,我们可以将数字处理设置为 AllowNamedFloatingPointLiterals 以获得相同的行为
那么,我们如何让 rust/serde_json 做同样的事情 - serde_json某处是否有标志来执行此操作,如果没有,添加此功能的最简单方法是什么?(我的意思是作为用户实现此功能,而不是通过更新serde_json源或分叉它或其他任何东西)。
编辑:在一些评论之后,假设我们同意JSON有问题,是否有一种格式可以用来代替JSON,完全支持浮点数。
或者,如何实现 JSON 有效的替代方案,例如使用“Infinity”作为字符串。据我所知,这将影响所有其他序列化,因此,如果您将结构序列化为 BSON、CBOR、msgpack 等。
再次编辑
因此,我自己的研究提出了几种可能性:
- JSON5 显然是在 JSON 的基础上扩展的,同时向后兼容。
- 可能有一些神奇的诡计可以用 serde 未标记的枚举来完成,但我不知道这是否属实。似乎 serde 可以依次尝试一系列格式,直到一种格式成功 - 如果它尝试序列化一个特殊的浮点数(严格来说,这是 JSON 规范所说的它应该做的),有没有办法使serde_json失败)。如果是这样,我们可以将其用作后备方案?
答:
它不受支持。
维护者的答案并不完全清楚,因为我认为serde_json公开了可以添加回退的反序列化器钩子,我认为通常的解决方案()为时已晚。deserialize_with
因此,您可能想要求精度,但乍一看,您似乎必须维护自定义的 serde_json 供应商/分支才能支持非标准扩展。
评论
null
serde_json
可以处理这些特殊的浮子吗?不可以,因为它严格遵守 JSON 规范。但是,JSON5 支持这些时髦的浮点数,并且serde_json5
忠实地实现了 JSON5:
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let map = HashMap::<_, _>::from_iter([
("a", 1.0),
("b", f64::NAN),
("c", f64::INFINITY),
("d", f64::NEG_INFINITY),
]);
let j = serde_json5::to_string(&map)?;
let o = serde_json5::from_str::<HashMap<String, f64>>(&j)?;
println!("JSON5: {}", j);
println!("HashMap: {:?}", o);
Ok(())
}
输出:
JSON5: {"a":1,"b":NaN,"d":-Infinity,"c":Infinity}
HashMap: {"a": 1.0, "d": -inf, "c": inf, "b": NaN}
评论
from_reader
from_slice
Read
评论
{"a": Infinity}
不是 JSON,因此使用通用的 JSON 序列化库来解析此数据可能会导致您出现问题。拥有标准化的数据格式允许不同的应用程序相互通信,如果一个应用程序不遵循标准,尝试以相同的方式破坏其他应用程序是错误的方法 - 而是修复损坏的应用程序。另一方面,是完全有效的 Json,您可以轻松创建一个能够反序列化该 JSON 的结构类型。{"a": "Infinity"}