如何使用serde将结构序列化为另一个Rust数据结构?

时间:2019-08-13 12:43:08

标签: rust serde

我有一个数据结构 Listener listener = new Listener( onPointerUp: (PointerUpEvent event) { print('${event.position}'); final RenderBox box = context.findRenderObject(); final Offset localOffset = box.globalToLocal(event.position); print(box); var res = BoxHitTestResult(); box.hitTest(res, position: localOffset); for (var r in res.path) { if (r.target is RenderMetaData) { var target = r.target as RenderMetaData; print(target.metaData); } } }); ,我想将该序列化为其他Rust结构。它基本上是内部字段的Document,但是它与数据库API交互,因此,我肯定会希望将其他类型转换为这些HashMap

例如这个结构

Document

我已经使用struct Entry { id: String, user: String, duration: u32, location: (f64, f64), } 特性转换为Document类型,但是当From结构更改时,这是我必须修改的额外地方。该实现使用Entry,如下所示:

DocumentBuilder

impl From<Entry> for Document { fn from(entry: Entry) -> Self { Document::builder() .name(&entry.id) // set the name of the document .field("user", entry.user) // add fields ... .field("duration", entry.duration) .field("location", entry.location) .build() // build a Document } } 方法可以将可以转换为field的任何值分配给键。因此FieldValue的签名是:

field

我想使用serde及其派生功能将结构及其字段自动序列化为impl DocumentBuilder { // ... pub fn field<T: Into<FieldValue>>(mut self, key: &str, value: T) -> Self { ... } // ... } 。我将如何去做呢?我查看了Implementing a Serializer的Wiki,但显示的示例写入了一个字符串,我想知道如何使用构建器模式将其序列化为数据结构。

1 个答案:

答案 0 :(得分:1)

最简单的方法是使用serde_json::from_value(即使您不使用JSON也适用,但要求所有字段均为有效JSON [例如,哈希图中没有非字符串键]):< / p>

let entry = Entry {
    a: 24,
    b: 42,
    c: "nice".to_string()
};
let v = serde_json::to_value(&entry).unwrap();
let document: Document = serde_json::from_value(v).unwrap();

注意:Document的值类型必须实现Deserialize,并且必须以某种方式将任何值反序列化为正确的参数。可以使用#[serde(untagged)]完成此操作,但是可能会导致某些类型错误,例如将u8转换为u64

Full playground example

一种不涉及任何不必要的副本的更复杂的方法将要求您编写一个自定义(De)序列化器,而一个很好看的方法是serde_transcode::transcode,它与您所做的事情相反想要-它在两种数据格式之间转换。