1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10pub struct OntologyReference {
11 #[serde(rename = "@type", skip_serializing_if = "Option::is_none")]
15 pub r#type: Option<String>,
16 pub id: String,
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub version: Option<String>,
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub uri: Option<String>,
24}
25
26impl OntologyReference {
27 #[must_use]
29 pub const fn new(id: String) -> Self {
30 Self {
31 r#type: None,
32 id,
33 version: None,
34 uri: None,
35 }
36 }
37
38 #[must_use]
40 pub fn with_version(mut self, version: String) -> Self {
41 self.version = Some(version);
42 self
43 }
44
45 #[must_use]
47 pub fn with_uri(mut self, uri: String) -> Self {
48 self.uri = Some(uri);
49 self
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::OntologyReference;
56
57 #[test]
58 fn round_trips_through_json() {
59 let reference = OntologyReference::new("grazing-plan".to_string())
60 .with_version("1.0.0".to_string())
61 .with_uri("https://mif-spec.dev/ontologies/grazing-plan".to_string());
62 let json = serde_json::to_string(&reference).unwrap();
63 let parsed: OntologyReference = serde_json::from_str(&json).unwrap();
64 assert_eq!(reference, parsed);
65 }
66
67 #[test]
68 fn omits_absent_optional_fields() {
69 let reference = OntologyReference::new("mif-base".to_string());
70 let json = serde_json::to_value(&reference).unwrap();
71 assert!(json.get("version").is_none());
72 assert!(json.get("uri").is_none());
73 assert!(json.get("@type").is_none());
74 }
75}