【发布时间】:2020-12-18 05:24:03
【问题描述】:
我有一个用例需要将 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 时似乎是不可能的。
直观地说,这必须是一个常见的用例......有没有办法解决这个不涉及:
- 将数据反序列化为
HashMap<String, String> - 遍历地图,将值解析为新
HashMap<String, Uri>
【问题讨论】:
-
您能否澄清一下为什么列出的两种方法是不可接受的?您可以创建自己的
struct MyUri(Uri)并在其上实现Deserialize以获得HashMap<String, MyUri>。 -
这是我得到的,我相信它可以改进以适应
2(no iter)--> play.rust-lang.org/… -
您可以按照@kmdreko 的建议避免进入并使用 MyUri
-
谢谢你们的帮助! @kmdreko 这不一定是不可接受的;将每个值加载到内存中两次(尤其是当真实世界的 JSON 对象包含数十万个条目时)只是感觉不太理想,我认为必须有更聪明的方法来做到这一点。