gpt4 book ai didi

rust - 使用 serde_json 反序列化远程结构的映射

转载 作者:行者123 更新时间:2023-12-02 02:28:38 25 4
gpt4 key购买 nike

我有一个用例,需要将 JSON 反序列化为“远程”(在另一个 crate 中定义)结构的映射。我在这方面经历了一段可笑的困难时期,所以我一定错过了一些明显的东西。

以下本质上是所需的最终状态:

use hyper::Uri;
use serde_json;
use std::collections::HashMap;

fn main() {
let data = r#"
{
"/a": "http://example.com/86f7e437faa5a7fce15d1ddcb9eaeaea377667b8",
"/b": "http://example.com/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98",
"/c": "http://example.com/84a516841ba77a5b4648de2cd0dfcb30ea46dbb4"
}"#;

let map: HashMap<String, Uri> = serde_json::from_str(data).unwrap();

println!("{:?}", map);
}

失败的原因是:

the trait bound `Uri: serde::de::Deserialize<'_>` is not satisfied required because of the requirements
on the impl of `serde::de::Deserialize<'_>` for `HashMap<std::string::String, Uri>`

虽然 serde 文档 describe a pretty nasty but potentially viable workaround用于推导Deserialize在远程结构上,它需要使用 #[serde(with = "LocalStructRedefinition")]在任何引用容器类型上,这在创建 HashMap 时似乎不可能.

直观上,这一定是一个常见的用例...有没有一种方法可以解决这个问题而不涉及:

  1. 将数据反序列化为 HashMap<String, String>
  2. 迭代 map ,将值解析为 HashMap<String, Uri>

最佳答案

结合使用 Intodeserialize_withflatten,您可以实现您想要的效果:

use serde_json;
use std::collections::HashMap;
use hyper::Uri;
use serde::{de::Error, Deserialize, Deserializer};

#[derive(Debug, Deserialize)]
struct MyUri(#[serde(deserialize_with = "from_uri")] Uri);

#[derive(Debug, Deserialize)]
struct MyUriMap {
#[serde(flatten)]
inner: HashMap<String, MyUri>
}

impl Into<HashMap<String, Uri>> for MyUriMap {
fn into(self) -> HashMap<String, Uri> {
self.inner.into_iter().map(|x| (x.0, x.1.0)).collect()
}
}


fn from_uri<'de, D>(deserializer: D) -> Result<Uri, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(deserializer)?;
s.parse().map_err(D::Error::custom)
}


fn main() {
let data = r#"
{
"/a": "http://example.com/86f7e437faa5a7fce15d1ddcb9eaeaea377667b8",
"/b": "http://example.com/e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98",
"/c": "http://example.com/84a516841ba77a5b4648de2cd0dfcb30ea46dbb4"
}"#;

let map: MyUriMap = serde_json::from_str(data).unwrap();

// let map: HashMap<String, Uri> = map.into();
// I think to get HashMap<String, Uri> you have to do an iter as seen in the Into implementation
println!("{:?}", map);
}

参见Playground

PS。在我的回答中,要获取 HashMap 你必须执行迭代器,如 Into 实现中所示

关于rust - 使用 serde_json 反序列化远程结构的映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65352157/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com