将具有多个元素的 JSON 字段从字符串反序列化为 Vec<u8>s 的 Vec
Deserializing a JSON field with multiple elements from Strings to a Vec of Vec<u8>s
我有一个遵循以下示例的 json 结构:
{
"title": "This is the title of the document",
"content": "This is a much longer entry containing the full content of a document",
"version_author": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"predecessor": "Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu",
"co_authors": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"
]
}
我正在使用 serde_json 将我的 json 文件反序列化为以下 rust 结构:
#[derive(Deserialize)]
struct IpfsConsequence {
// Specify our own deserializing function to convert JSON string to vector of bytes
#[serde(deserialize_with = "de_string_to_bytes")]
title: Vec<u8>,
#[serde(deserialize_with = "de_string_to_bytes")]
content: Vec<u8>,
#[serde(deserialize_with = "de_string_to_bytes")]
version_author: Vec<u8>,
#[serde(deserialize_with = "de_string_to_bytes")]
predecessor: Vec<u8>,
co_authors: Vec<String>,
}
pub fn de_string_to_bytes<'de, D>(de: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(de)?;
Ok(s.as_bytes().to_vec())
}
这可以编译,我可以编写代码来完美地使用它。但是使用 co_authors 的 Vec 类型感觉有点乱。我更愿意使用 Vec 类型,但我找不到这样做的方法。
serde_json 很聪明,因为它能够将具有多个值的字段反序列化为 Vec。我希望它在我的 co_authors 字段中继续这样做。但是后来我希望它使用我的“de_string_to_bytes”反序列化器将 co_authors 字段中的每个值转换为 Vecs。
因为我只能将 #[serde(deserialize_with = "de_string_to_bytes")] 宏应用于我的结构中的整个字段,如果我这样做,它将覆盖默认值 serde_json 将具有多个值的字段反序列化为 Vec 的行为,我不想覆盖它。
您可以定义一个类似的函数,将 Vec<&str>
解码为 Vec<Vec<u8>>
:
pub fn de_vec_string_to_bytes<'de, D>(de: D) -> Result<Vec<Vec<u8>>, D::Error>
where
D: Deserializer<'de>,
{
let v: Vec<&str> = Deserialize::deserialize(de)?;
Ok(v.into_iter().map(|s| s.as_bytes().to_vec()).collect())
}
如果你想在更多数据结构中使用它,最好创建一个包装 Vec<u8>
实现 Deserialize
的新类型,然后在任何地方使用该类型:
use std::collections::HashMap;
use serde::{Deserialize, Deserializer};
#[derive(Deserialize)]
struct IpfsConsequence {
title: Bytes,
co_authors: Vec<Bytes>,
maybe_a_map_too: HashMap<String, Bytes>,
}
#[derive(Deserialize)]
struct Bytes(#[serde(deserialize_with = "de_string_to_bytes")] Vec<u8>);
pub fn de_string_to_bytes<'de, D>(de: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(de)?;
Ok(s.as_bytes().to_vec())
}
我有一个遵循以下示例的 json 结构:
{
"title": "This is the title of the document",
"content": "This is a much longer entry containing the full content of a document",
"version_author": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"predecessor": "Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu",
"co_authors": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"
]
}
我正在使用 serde_json 将我的 json 文件反序列化为以下 rust 结构:
#[derive(Deserialize)]
struct IpfsConsequence {
// Specify our own deserializing function to convert JSON string to vector of bytes
#[serde(deserialize_with = "de_string_to_bytes")]
title: Vec<u8>,
#[serde(deserialize_with = "de_string_to_bytes")]
content: Vec<u8>,
#[serde(deserialize_with = "de_string_to_bytes")]
version_author: Vec<u8>,
#[serde(deserialize_with = "de_string_to_bytes")]
predecessor: Vec<u8>,
co_authors: Vec<String>,
}
pub fn de_string_to_bytes<'de, D>(de: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(de)?;
Ok(s.as_bytes().to_vec())
}
这可以编译,我可以编写代码来完美地使用它。但是使用 co_authors 的 Vec 类型感觉有点乱。我更愿意使用 Vec
serde_json 很聪明,因为它能够将具有多个值的字段反序列化为 Vec。我希望它在我的 co_authors 字段中继续这样做。但是后来我希望它使用我的“de_string_to_bytes”反序列化器将 co_authors 字段中的每个值转换为 Vecs。
因为我只能将 #[serde(deserialize_with = "de_string_to_bytes")] 宏应用于我的结构中的整个字段,如果我这样做,它将覆盖默认值 serde_json 将具有多个值的字段反序列化为 Vec 的行为,我不想覆盖它。
您可以定义一个类似的函数,将 Vec<&str>
解码为 Vec<Vec<u8>>
:
pub fn de_vec_string_to_bytes<'de, D>(de: D) -> Result<Vec<Vec<u8>>, D::Error>
where
D: Deserializer<'de>,
{
let v: Vec<&str> = Deserialize::deserialize(de)?;
Ok(v.into_iter().map(|s| s.as_bytes().to_vec()).collect())
}
如果你想在更多数据结构中使用它,最好创建一个包装 Vec<u8>
实现 Deserialize
的新类型,然后在任何地方使用该类型:
use std::collections::HashMap;
use serde::{Deserialize, Deserializer};
#[derive(Deserialize)]
struct IpfsConsequence {
title: Bytes,
co_authors: Vec<Bytes>,
maybe_a_map_too: HashMap<String, Bytes>,
}
#[derive(Deserialize)]
struct Bytes(#[serde(deserialize_with = "de_string_to_bytes")] Vec<u8>);
pub fn de_string_to_bytes<'de, D>(de: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(de)?;
Ok(s.as_bytes().to_vec())
}