1 个不稳定版本
0.1.0 | 2022年12月22日 |
---|
#1804 in 编码
27KB
588 行
serde_extract
使具有 Serialize
的值转换为 Deserializer
实际上,这允许从一个实现了 Serialize
的结构体中提取一个实现了 Deserialize
的结构体。
使用方法
TL;DR
#[derive(serde_derive::Serialize)]
struct Source<'a> {
a: &'a str,
b: u32,
}
#[derive(Debug, PartialEq, serde_derive::Deserialize)]
struct Extract {
b: u32,
}
assert_eq!(
Extract { b: 3 },
serde_extract::extract(&Source { a: "hello", b: 3 }).unwrap(),
);
更实际的例子
假设我们处于一个需要实现分页的SDK的场景中,我们只需要发送一次原始查询,但如果原始查询中提供了 page_size
,则需要重新发送它。由于管理分页的代码不了解底层结构,并且由于将 page_size
参数添加到我们的 make_paginated_request
函数将非常不灵活(假设)并且更倾向于将其与查询参数的其他部分一起指定,因此这是一个适合此crate的使用场景。
// This will be our original query
#[derive(serde_derive::Serialize)]
struct SomeSpecificRequest {
field_a: &'static str,
page_size: usize,
}
// Let's say make_request is our generic function that makes a call to the server
make_paginated_request(&SomeSpecificRequest {
field_a: "hello!",
page_size: 2,
})
.expect("Failed to make request");
fn make_paginated_request<S: serde::Serialize>(
serializable: &S,
) -> Result<(), Box<dyn std::error::Error>> {
#[derive(serde_derive::Deserialize)]
struct MaybePageSize {
page_size: Option<usize>,
}
// We will reuse the page size for the subsequent paginated requests if it was
// provided in the original query, so we need to extract it
let page_size_for_this_request =
serde_extract::extract::<MaybePageSize, _>(serializable)?.page_size;
// this works:
assert_eq!(page_size_for_this_request, Some(2));
// Make request...
Ok(())
}
限制
- 目前不支持序列(尽管理论上可以添加支持,生成代码的算法复杂度为O(n²),其中n是序列中元素的数量,因为我们需要通过
MapAccess
通过Visitor
重新驱动每个元素调用Serializer
) - 出于同样的原因,目前不支持将数据反序列化为
map
。具体来说,目前我们只能提取具有通过deserialize_struct
指示的名称的字段。(这允许驱动Serializer
的次数与要提取的字段数相同。在实际中,如果双方都是常规结构体,优化器可能将其转换为零成本提取。在理论上,支持将数据反序列化为maps可以添加,其算法复杂度为O(n²),其中n是输入字段的数量。)
依赖项
~120–360KB