防止Rust中的序列化结构被重命名为不同的结构

qij5mzcb  于 2024-01-08  发布在  其他
关注(0)|答案(1)|浏览(117)

我想防止具有相同属性名称的数据,但不同的语义不能意外地加载到另一个中。例如:

use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Debug)]
#[serde(deny_unknown_fields)]
struct RubyVersionV1 {
    // Records explicit or default version we want to install
    version: String,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(deny_unknown_fields)]
struct RubyVersionV2 {
    // Programmer realized that there was ambiguity in their prior storage schema
    //
    // They want to decouple an explicit version, from the default case.
    // To make this change they switch to using an Option stores None
    // when a default is used, and Some when an explicit version is used.
    version: Option<String>,
}

// Both use a trait to deliver the information the program needs
trait RubyVersion {
    fn version_to_install(&self) -> String;
}

impl RubyVersion for RubyVersionV1 {
    fn version_to_install(&self) -> String {
        self.version.clone()
    }
}

const DEFAULT_VERSION: &str = "3.2.2";

impl RubyVersion for RubyVersionV2 {
    fn version_to_install(&self) -> String {
        self.version
            .clone()
            .unwrap_or_else(|| DEFAULT_VERSION.to_string())
    }
}

字符串
可运行示例:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=94308306cf81e0fcaff06fb3a2457a6b
在这段代码中,从RubyVersionV1序列化到磁盘的数据可能会意外地被序列化为RubyVersionV2
这是一个简单的例子,试图演示我正在处理的更复杂的域(PR https://github.com/heroku/buildpacks-ruby/pull/246)。如果我能保证V1永远不会被转换为V2(而不是要求程序员小心),那么我的用户的生活会容易得多。

0g0grzrc

0g0grzrc1#

你可以通过在每个结构体中添加一个void字段来作为版本标记:

use serde::{ Serialize, Deserialize };

#[derive (Serialize, Deserialize, Debug, Default)]
struct V1 {
    text: String,
    version1: (),
}

#[derive (Serialize, Deserialize, Debug, Default)]
struct V2 {
    text: Option<String>,
    version2: (),
}

fn main() {
    let v1 = V1::default();
    let s1 = serde_json::to_string (&v1).unwrap();
    let v2: Result<V2, _> = serde_json::from_str (&s1);
    println!("{v1:?} -> {s1} -> {v2:?}");
}

字符串
Playground

相关问题