【问题标题】:How do I use Serde to deserialize malformed JSON with True/False?如何使用 Serde 反序列化带有 True/False 的格式错误的 JSON?
【发布时间】: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);
}

runnable on the playground

据我所知,问题在于输入未被识别为任何正确的类型,因此visitor APIs 在这里不起作用。

更新(2020-02-05)

显然这是不可能用serde_json 解决的(一种方法是使用自定义数据格式或派生serde_json 以添加此功能,因为serde_json 不处理无效输入,请参阅维护者的answer)。

对于遇到类似问题的其他人来说,一个 hacky 解决方案是将原始响应字符串中的 TrueFalse 实例替换为 truefalse。这绝对不是完美的,因为如果字符串包含 TrueFalse,它们也会被替换,但对于特定用例来说,这可能是一个可接受的解决方案。

【问题讨论】:

  • 我没有尝试运行您的示例,但我认为 if v == &amp;['T' as u8, 'r' as u8, 'e' as u8] { 行中有错字,因为您拼写的是“Tre”而不是“True”。 HTH。

标签: json rust serde malformed


【解决方案1】:

一般而言,如果输入采用库所针对的数据格式,您只能使用特定库对输入进行反序列化。

例如,如果您的输入不是 JSON、CBOR、MessagePack,那么您不能使用 serde_json、serde_cbor 或 serde_messagepack 对其进行反序列化。

您显示的输入似乎是 YAML,因此您可以尝试 serde_yaml。

fn main() {
    let input = r#" {
                      "value": True
                    } "#;
    println!("{:#?}", serde_yaml::from_str::<serde_yaml::Value>(input).unwrap());
}

换句话说,数据无效 JSON 的事实告诉您使用哪个库 not — serde_json。要找到正确的库,找到数据有效的格式会更有用。

【讨论】:

【解决方案2】:

这是无效的 JSON,因此您不能使用 serde_json 对其进行反序列化。

JSON 中的布尔常量为 truefalse,小写。

【讨论】:

  • 不幸的是,我无法更改源格式(我正在与第三方后端集成)。除了使用手动 JSON 解析器手动反序列化字符串之外,这里还有其他可能的解决方法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-30
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多