首页 > 解决方案 > avro-rs 解释 `uuid` 给出 SerdeError

问题描述

我正在尝试使用avro_rs将数据反序列化为带有Uuid字段的结构。

use avro_rs::types::Value;
use serde::Deserialize;
use uuid::Uuid;

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Metadata {
    pub event_uuid: Uuid,
}

fn main() {
    let uuid = Value::Uuid(Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8").unwrap());
    let avro_uuid = avro_rs::from_value::<Uuid>(&uuid);
    eprintln!("avro_uuid = {:#?}", avro_uuid);

    let metadata = Value::Record(vec![("eventUuid".to_owned(), uuid)]);
    let avro_metadata = avro_rs::from_value::<Metadata>(&metadata);
}

货运.toml

[package]
name = "pp-avro"
version = "0.1.0"
edition = "2018"

[dependencies]

avro-rs = { version = ">= 0.6" }
serde = "1.0"
serde_json = "1.0"
uuid = { version = "0.8.1", features = ["serde", "v4"] }

这给了我错误:

avro_uuid = Err(
    Error {
        message: "not a string|bytes|fixed",
    },
)

创建Metadata对象是不可能的。

标签: serializationrustavrouuidserde

解决方案


我不是 avro_rs 专家,但这是我的直觉:

fn main() -> Result<(), Box<dyn Error>> {
    let uuid = Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8").unwrap();
    let uuid_val = Value::Uuid(uuid.clone());
    let metadata = Metadata { event_uuid: uuid };
    let ser = avro_rs::to_value(&metadata)?;
    println!("{:?}", ser);
    Ok(())
}

这段代码打印出来:

Record([("eventUuid", String("936da01f-9abd-4d9d-80c7-02af85c822a8"))])

正如您已经建议的那样,能够运行是有意义的:

let uuid = Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8").unwrap();
let uuid_val = Value::Uuid(uuid);
let metadata = Value::Record(vec![("eventUuid".to_owned(), uuid_val)]);
println!("{:?}", metadata);
avro_rs::from_value::<Metadata>(&metadata)?;

这是一个 MRE,它失败了:

Error: Error { message: "not a string|bytes|fixed" }

我的猜测是,这要么是一个错误,要么是当您想从 a 反序列化Value而不提供架构时所期望的。


老答案:

您尚未添加 Cargo.toml 的内容,但如果您使用的是此库:

我认为您错过了该serde功能的规范,根据自述文件:

 * serde - adds the ability to serialize and deserialize a Uuid using the serde crate.

所以在你的 Cargo.toml 中,你应该有这样的东西:

uuid = { version = "0.8", features = ["serde"] }

推荐阅读