rust - Rust定制反序列化实现

标签 rust serde

我很难理解如何使用Rust的serde实现自定义映射的反序列化。如果有人可以帮助我解决此示例,我将感到非常高兴:
我有以下结构:

#[derive(Debug, Clone, PartialEq)]
pub struct ConnectorTopics {
    pub name: String,
    pub topics: Vec<String>,
}
JSON数据采用以下格式:
{
  "test-name": {
    "topics": [
      "topic1",
      "topic2"
    ]
  }
}
如您所见,name字段是主题的包装,因此在我的情况下,应反序列化为:
let _ = ConnectorTopics {
    name: "test-name".into(),
    topics: vec!["topic1".into(), "topic2".into()]
}
我的第一个尝试是在Deserialize实现中使用自定义结构,但是这种方法无法编译,而且似乎也不是正确的方法。
impl<'de> Deserialize<'de> for ConnectorTopics {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Debug, Deserialize)]
        struct Inner {
            topics: Vec<String>,
        }

        let a = deserializer.deserialize_map(HashMap<String, Inner>).unwrap();

        

        let value = Deserialize::deserialize::<HashMap<String, Inner>>(deserializer)?;

        let (connector, inner) = value.iter().nth(0).ok_or("invalid")?.0;

        Ok(ConnectorTopics {
            name: connector,
            topics: vec![],
        })
    }
}

最佳答案

您正在做的是正确的方法,但是您的json很奇怪:

use serde::de;
use serde::Deserialize;
use std::fmt;

#[derive(Debug, Clone, PartialEq)]
pub struct ConnectorTopics {
    pub name: String,
    pub topics: Vec<String>,
}

#[derive(Debug, Deserialize)]
struct Inner {
    topics: Vec<String>,
}

impl<'de> de::Deserialize<'de> for ConnectorTopics {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        struct ConnectorTopicsVisitor;

        impl<'de> de::Visitor<'de> for ConnectorTopicsVisitor {
            type Value = ConnectorTopics;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("ConnectorTopics")
            }

            fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
            where
                V: de::MapAccess<'de>,
            {
                if let Some(key) = map.next_key()? {
                    let value: Inner = map.next_value()?;
                    if let Some(_) = map.next_key::<&str>()? {
                        Err(de::Error::duplicate_field("name"))
                    } else {
                        Ok(Self::Value {
                            name: key,
                            topics: value.topics,
                        })
                    }
                } else {
                    Err(de::Error::missing_field("name"))
                }
            }
        }

        deserializer.deserialize_map(ConnectorTopicsVisitor {})
    }
}

fn main() {
    let input = r#"{
      "test-name": {
        "topics": [
          "topic1",
          "topic2"
        ]
      }
    }"#;

    let result: ConnectorTopics = serde_json::from_str(input).unwrap();

    let expected = ConnectorTopics {
        name: "test-name".into(),
        topics: vec!["topic1".into(), "topic2".into()],
    };

    assert_eq!(result, expected);
}

关于rust - Rust定制反序列化实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66135063/

相关文章:

rust - dyn MyTrait的大小无法在采用self的方法中静态确定。

serialization - 通过实现 serde `Deserializer` 将值的 Vec 反序列化为结构体

rust - 即使使用::from 我得到预期的类型参数 A 错误

performance - repeat(x).take(n) 性能好吗?

rust - 为什么没有为明确实现的类型实现特征?

json - 如何将多个键值条目的 JSON 对象反序列化为 Rust 中的自定义结构

rust - 如何在Rust(使用serde)中反序列化可选的json参数,该参数可以是字符串或字符串数​​组

error-handling - 如何在不使整个反序列化失败的情况下使用 Serde 解析可能无法反序列化的字段?

Rust 类型不匹配但前提是我不使用类型注释

postgresql - Rust Actix-Web sqlx 可选功能 `time` 需要列 #4 ("created_at"的 TIMESTAMPTZ 类型)