我可以将 RMPV `Value` 发送回 rmp_serde 以进行反序列化吗?
Can I send an RMPV `Value` back to rmp_serde for deserialization?
我有一个大的、有点复杂的数据结构,我可以使用 serde
和 rmp-serde
对其进行序列化和反序列化,但我发现反序列化速度很慢。我认为这是因为我的数据结构包括两个相当大的 HashMap。我不知道 rmp_serde::from_slice
创建 HashMap 的效率如何——它会使用 .with_capacity
初始化还是只创建一个 HashMap 并逐一插入?此外,我发现 AHashMap 在其他地方给了我相当大的性能改进,所以我尽量避免使用默认的 HashMap。
我想尝试使用 rmpv::decode::value::read_value
, but I'd like to leave most of the deserialization to rmp_serde and only implement some deserialization myself given some Value
进行反序列化。有没有办法选择我手动反序列化哪些片段?
从概念上讲,我想做的是:
let v = rmp::decode::read_value(&mut reader).unwrap(); // get some Value
let arr : &Vec<Value> = v.as_array().unwrap(); // v is known to be an array
let first_value : MyType = deserialize_manually(arr[0]); // I'll convert the Value myself
let second_value : AnotherType = arr[1].into(); // allow rmpv to convert Value for me
我目前使用的是 rmp-serde 0.14 和 rmpv 0.4.7。 The rmp_serde changelog and rmp_serde release page 没有提供有关更改内容的详细信息,因此我还没有理由相信升级到当前版本(撰写此问题时为 v0.15.4)会提供任何新功能。
我知道serde提供了一个deserialize_with
attribute。也许这是合适的路线,所以或者,我的问题是:如何使用 deserialize_with
反序列化特定的 MsgPack 字段?
我能够使用 deserialize-with
让它工作。首先,我必须注释我的结构:
struct MyStruct {
some_number: i32,
#[serde(deserialize_with="de_first_value")]
first_value : HashMap<i32, String>, // T1 & T2 don't matter
second_value : AnotherType,
}
然后我创建这个函数来驱动反序列化。因为我正在反序列化 HashMap
,所以我遵循 serde 的 Implement Deserialize for a custom map type:
fn de_first_value<'de, D>(deserializer: D) -> Result<HashMap<i32, String>, D::Error>
where
D: serde::de::Deserializer<'de>,
{
deserializer.deserialize_byte_buf(MyHmVisitor)
}
然后我定义 MyHmVisitor
并实现 the Visitor trait. For deserializing a HashMap, I have to implement the visit_map
function; I assume that I could do a similar deserialization for other types in this way by implementing the default provided methods(除非被覆盖,否则它们都会因类型错误而失败):
struct MyHmVisitor;
impl<'de> serde::de::Visitor<'de> for MyHmVisitor {
type Value = HashMap<i32, String>;
/// "This is used in error messages. The message should complete the sentence
/// 'This Visitor expects to receive ...'"
/// https://docs.serde.rs/src/serde/de/mod.rs.html#1270
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "a HashMap<i32, String>")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
// extract the size hint from the serialized map. If it doesn't exist, default to 0
let capacity = map.size_hint().unwrap_or(0);
let mut hm = HashMap::with_capacity(capacity);
while let Some((k, v)) = map.next_entry()? {
hm.insert(k,v);
}
hm
}
}
我有一个大的、有点复杂的数据结构,我可以使用 serde
和 rmp-serde
对其进行序列化和反序列化,但我发现反序列化速度很慢。我认为这是因为我的数据结构包括两个相当大的 HashMap。我不知道 rmp_serde::from_slice
创建 HashMap 的效率如何——它会使用 .with_capacity
初始化还是只创建一个 HashMap 并逐一插入?此外,我发现 AHashMap 在其他地方给了我相当大的性能改进,所以我尽量避免使用默认的 HashMap。
我想尝试使用 rmpv::decode::value::read_value
, but I'd like to leave most of the deserialization to rmp_serde and only implement some deserialization myself given some Value
进行反序列化。有没有办法选择我手动反序列化哪些片段?
从概念上讲,我想做的是:
let v = rmp::decode::read_value(&mut reader).unwrap(); // get some Value
let arr : &Vec<Value> = v.as_array().unwrap(); // v is known to be an array
let first_value : MyType = deserialize_manually(arr[0]); // I'll convert the Value myself
let second_value : AnotherType = arr[1].into(); // allow rmpv to convert Value for me
我目前使用的是 rmp-serde 0.14 和 rmpv 0.4.7。 The rmp_serde changelog and rmp_serde release page 没有提供有关更改内容的详细信息,因此我还没有理由相信升级到当前版本(撰写此问题时为 v0.15.4)会提供任何新功能。
我知道serde提供了一个deserialize_with
attribute。也许这是合适的路线,所以或者,我的问题是:如何使用 deserialize_with
反序列化特定的 MsgPack 字段?
我能够使用 deserialize-with
让它工作。首先,我必须注释我的结构:
struct MyStruct {
some_number: i32,
#[serde(deserialize_with="de_first_value")]
first_value : HashMap<i32, String>, // T1 & T2 don't matter
second_value : AnotherType,
}
然后我创建这个函数来驱动反序列化。因为我正在反序列化 HashMap
,所以我遵循 serde 的 Implement Deserialize for a custom map type:
fn de_first_value<'de, D>(deserializer: D) -> Result<HashMap<i32, String>, D::Error>
where
D: serde::de::Deserializer<'de>,
{
deserializer.deserialize_byte_buf(MyHmVisitor)
}
然后我定义 MyHmVisitor
并实现 the Visitor trait. For deserializing a HashMap, I have to implement the visit_map
function; I assume that I could do a similar deserialization for other types in this way by implementing the default provided methods(除非被覆盖,否则它们都会因类型错误而失败):
struct MyHmVisitor;
impl<'de> serde::de::Visitor<'de> for MyHmVisitor {
type Value = HashMap<i32, String>;
/// "This is used in error messages. The message should complete the sentence
/// 'This Visitor expects to receive ...'"
/// https://docs.serde.rs/src/serde/de/mod.rs.html#1270
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "a HashMap<i32, String>")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
// extract the size hint from the serialized map. If it doesn't exist, default to 0
let capacity = map.size_hint().unwrap_or(0);
let mut hm = HashMap::with_capacity(capacity);
while let Some((k, v)) = map.next_entry()? {
hm.insert(k,v);
}
hm
}
}