【发布时间】:2020-02-03 22:23:19
【问题描述】:
如何使用 Rust 的 serde 反序列化以下格式错误的 JSON:
{
"value": True
}
使用this answer,我尝试了以下解决方案:
#[macro_use]
extern crate serde_derive; // 1.0.66
extern crate serde; // 1.0.66
extern crate serde_json; // 1.0.21
use serde::de;
use std::fmt;
#[derive(Debug, PartialEq, Deserialize)]
pub struct Foo {
#[serde(deserialize_with = "deserialize_capitalized_bool")]
pub bar: bool,
}
fn deserialize_capitalized_bool<'de, D>(
deserializer: D,
) -> Result<bool, D::Error>
where
D: de::Deserializer<'de>,
{
struct CapitalizedBoolVisitor;
impl<'de> de::Visitor<'de> for CapitalizedBoolVisitor {
type Value = bool;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a True or False string")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
if v == &['T' as u8, 'r' as u8, 'e' as u8] {
Ok(true)
} else if v
== &['F' as u8, 'a' as u8, 'l' as u8, 's' as u8, 'e' as u8]
{
Ok(false)
} else {
unimplemented!();
}
}
}
deserializer.deserialize_any(CapitalizedBoolVisitor)
}
fn main() {
let json = r#"{
"bar": True
}"#;
let foo: Foo = serde_json::from_str(json).unwrap();
let expected = Foo {
bar: true
};
assert_eq!(foo, expected);
}
据我所知,问题在于输入未被识别为任何正确的类型,因此visitor APIs 在这里不起作用。
更新(2020-02-05):
显然这是不可能用serde_json 解决的(一种方法是使用自定义数据格式或派生serde_json 以添加此功能,因为serde_json 不处理无效输入,请参阅维护者的answer)。
对于遇到类似问题的其他人来说,一个 hacky 解决方案是将原始响应字符串中的 True 和 False 实例替换为 true 和 false。这绝对不是完美的,因为如果字符串包含 True 或 False,它们也会被替换,但对于特定用例来说,这可能是一个可接受的解决方案。
【问题讨论】:
-
我没有尝试运行您的示例,但我认为
if v == &['T' as u8, 'r' as u8, 'e' as u8] {行中有错字,因为您拼写的是“Tre”而不是“True”。 HTH。