我试图在rust中创建一个灵活但特定类型的结构体。让我们将结构体命名为Analysis
。所有Analysis
结构体必须具有字段name
,id
,created
,modified
。但有3种不同的分析:
// all enums and struct use the #[derive(Serialize, Deserialize, ToSchema)] macro
pub enum AnalysisTypes {
Chemical,
Physical,
Biological,
}
字符串
每种特定的分析类型都有自己的特定字段:
pub struct ChemicalAnalysis {
statistics: Vec<Statistic>, // doesn't matter what this is exactly
method_parameters: MethodParameters,
}
pub struct PhysicalAnalysis {
statistics: Vec<Statistic>,
}
pub struct BiologicalAnalysis {
sampling_information: Vec<SampleInformation>,
}
型
我的目标是创建一个结构体Analysis
,它具有上面提到的所有公共属性,以及上面提到的分析结构体中的所有属性。所以我创建了一个枚举,它可以是其中的任何一个,然后将它包含在我的结构体中:
pub enum AnalysisEnum {
Chemical(ChemicalAnalysis),
Physical(PhysicalAnalysis),
Biological(BiologicalAnalysis),
}
pub struct Analysis {
name: String,
id: Uuid,
created: DateTime<Utc>,
modified: DateTime<Utc>,
#[serde(flatten)] // <------------ flatten values into struct here
more_fields: AnalysisEnum,
}
型serde(flatten)
almost 得到了我想要的。当我在OpenAPI文档中检查这个时,分析结构体将始终具有“common”字段,并且需要一个名称为Chemical,Physical或Biological的条目,每个条目都有各自的字段。
的数据
我想对这些属性进行“去 shell 化”,让它们直接扁平化到父结构体中,而不是要求它们在一个命名的属性下。
另外,我如何在父Analysis
结构analysis_type
中要求一个属性,即AnalysisEnum类型,专门对应于每个AnalysisEnum?例如:
pub enum AnalysisTypes {
Chemical,
Physical,
Biological,
}
pub struct ChemicalAnalysis {
analysis_type: AnalysisTypes::Chemical, // this is not correct syntax, errors
statistics: Vec<Statistic>,
method_parameters: MethodParameters,
}
pub struct PhysicalAnalysis {
analysis_type: AnalysisTypes::Physical, // this is not correct syntax, errors
statistics: Vec<Statistic>,
}
...
型
如果这是一个简单的问题,或者我想要的设计模式不符合语言的精神,请原谅我。我来自打字脚本背景,在那里可以很容易地做到这一点:
enum AnalysisTypes {
Chemical = "Chemical",
Physical = "Physical",
Biological = "Biological",
}
interface ChemicalAnalysis {
analysis_type: AnalysisTypes.Chemical,
statistics: Statistic[],
method_parameters: MethodParameters,
}
interface PhysicalAnalysis {
analysis_type: AnalysisTypes.Physical,
statistics:Statistic[],
}
interface BiologicalAnalysis {
analysis_type: AnalysisTypes.Biological,
sampling_information:SampleInformation[],
}
type Analysis = {
name: String;
id: Uuid;
created: DateTime<Utc>;
modified: DateTime<Utc>;
} & (ChemicalAnalysis | PhysicalAnalysis | BiologicalAnalysis)
型
2条答案
按热度按时间k7fdbhmy1#
您要查找的内容名为
#[serde(tag = "analysis_type")]
(您可以将`“analysis_type”)]”替换为您要用于存储标记的字段的名称)。字符串
(Playground ]
有关如何在Serde中表示枚举的完整参考,请参见https://serde.rs/enum-representations.html。
rt4zxlrg2#
既然可以创建一个枚举,为什么还要创建五个不同的类型(
AnalysisEnum
、AnalysisType
、ChemicalAnalysis
、PhysicalAnalysis
、BiologicalAnalysis
)呢?字符串
我想对这些属性进行“去壳”,并将它们直接展平到父结构中,而不是要求它们位于命名属性之下。我该如何做到这一点?
没有。大小类型就是大小类型,它不能根据运行时的值而改变。你必须把事情弄得很清楚。不过我可能对你真正想要的是错的。
serde
也许你只想要
tag = "type"
?我想要的设计图案...
感觉是这样。