我想防止具有相同属性名称的数据,但不同的语义不能意外地加载到另一个中。例如:
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(而不是要求程序员小心),那么我的用户的生活会容易得多。
1条答案
按热度按时间0g0grzrc1#
你可以通过在每个结构体中添加一个void字段来作为版本标记:
字符串
Playground