bo4e_core/
additional_attribute.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
8#[serde(untagged)]
9pub enum AttributeValue {
10 String(String),
12 Number(f64),
14 Boolean(bool),
16 Object(Vec<AdditionalAttribute>),
18 Array(Vec<AttributeValue>),
20 Null,
22}
23
24#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
41#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
42#[serde(rename_all = "camelCase")]
43pub struct AdditionalAttribute {
44 pub name: String,
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub value: Option<AttributeValue>,
49}
50
51impl AdditionalAttribute {
52 pub fn string(name: impl Into<String>, value: impl Into<String>) -> Self {
54 Self {
55 name: name.into(),
56 value: Some(AttributeValue::String(value.into())),
57 }
58 }
59
60 pub fn number(name: impl Into<String>, value: f64) -> Self {
62 Self {
63 name: name.into(),
64 value: Some(AttributeValue::Number(value)),
65 }
66 }
67
68 pub fn boolean(name: impl Into<String>, value: bool) -> Self {
70 Self {
71 name: name.into(),
72 value: Some(AttributeValue::Boolean(value)),
73 }
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_string_attribute() {
83 let attr = AdditionalAttribute::string("system_id", "ABC123");
84 assert_eq!(attr.name, "system_id");
85 assert_eq!(
86 attr.value,
87 Some(AttributeValue::String("ABC123".to_string()))
88 );
89 }
90
91 #[test]
92 fn test_number_attribute() {
93 let attr = AdditionalAttribute::number("priority", 42.0);
94 assert_eq!(attr.name, "priority");
95 assert_eq!(attr.value, Some(AttributeValue::Number(42.0)));
96 }
97
98 #[test]
99 fn test_serialize_attribute() {
100 let attr = AdditionalAttribute::string("key", "value");
101 let json = serde_json::to_string(&attr).unwrap();
102 assert_eq!(json, r#"{"name":"key","value":"value"}"#);
103 }
104
105 #[test]
106 fn test_deserialize_attribute() {
107 let json = r#"{"name":"key","value":"value"}"#;
108 let attr: AdditionalAttribute = serde_json::from_str(json).unwrap();
109 assert_eq!(attr.name, "key");
110 assert_eq!(
111 attr.value,
112 Some(AttributeValue::String("value".to_string()))
113 );
114 }
115
116 #[test]
117 fn test_deserialize_nested_attribute() {
118 let json = r#"{"name":"parent","value":[{"name":"child","value":123}]}"#;
119 let attr: AdditionalAttribute = serde_json::from_str(json).unwrap();
120 assert_eq!(attr.name, "parent");
121 match attr.value {
122 Some(AttributeValue::Object(children)) => {
123 assert_eq!(children.len(), 1);
124 assert_eq!(children[0].name, "child");
125 }
126 _ => panic!("Expected nested object"),
127 }
128 }
129}