0

我正在使用一个不太理想的 API,它不遵循任何严格的数据发送标准。每个有效负载在 JSON 之前都带有一些有效负载信息,然后是内部的实际数据,其中可以是单个字符串或多个字段。

就目前而言,如果我要将每个不同的有效负载映射到一个结构,我最终会得到大约 50 个结构。我觉得这并不理想,因为除了键之外,这些结构中的大量重叠。例如,我相信有 6 种不同版本的有效载荷可以映射到以下内容,但它们都有不同的键。

我有这两个 JSON 示例:

{"key": "string"}
{"key2": "string"}

我想将两者序列化到这个结构中:

#[derive(Debug, Deserialize)]
struct SimpleString {
    key: String,
}

两个字符串也可以这样说,甚至三个字符串也可以这样说。有效载荷在小方面是令人沮丧的独特,所以我目前的解决方案是在反序列化它们的函数内本地定义结构,然后将数据传递到需要去的任何地方(在我的情况下是缓存和事件处理程序)

有没有更好的方法来表示这个没有太多重复?我已经尝试寻找与密钥无关的反序列化之类的东西,但我还没有找到任何东西。

4

1 回答 1

1

您可以Deserialize为您的类型实现解码“地图”并忽略键名:

extern crate serde;
extern crate serde_json;

use std::fmt;
use serde::de::{Deserialize, Deserializer, Error, MapAccess, Visitor};

fn main() {
    let a = r#"{"key": "string"}"#;
    let b = r#"{"key2": "string"}"#;

    let a: SimpleString = serde_json::from_str(a).unwrap();
    let b: SimpleString = serde_json::from_str(b).unwrap();

    assert_eq!(a, b);
}

#[derive(Debug, PartialEq)]
struct SimpleString {
    key: String,
}

struct SimpleStringVisitor;

impl<'de> Visitor<'de> for SimpleStringVisitor {
    type Value = SimpleString;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("an object with a single string value of any key name")
    }

    fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
    where
        M: MapAccess<'de>,
    {
        if let Some((_, key)) = access.next_entry::<String, _>()? {
            if access.next_entry::<String, String>()?.is_some() {
                Err(M::Error::custom("too many values"))
            } else {
                Ok(SimpleString { key })
            }
        } else {
            Err(M::Error::custom("not enough values"))
        }
    }
}

impl<'de> Deserialize<'de> for SimpleString {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_map(SimpleStringVisitor)
    }
}
于 2017-12-14T21:08:49.093 回答