use crate::{
BodyListUrl, DateTime, EmailAddress, Name, OParlVersion, SystemUrl, Url,
namespace::SystemNamespaceUrl,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct System {
pub id: SystemUrl,
#[serde(rename = "type")]
pub namespace: SystemNamespaceUrl,
pub oparl_version: OParlVersion,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub other_oparl_versions: Vec<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license: Option<Url>,
pub body: BodyListUrl,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub contact_email: Option<EmailAddress>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub contact_name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub website: Option<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vendor: Option<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub product: Option<Url>,
pub created: DateTime,
pub modified: DateTime,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub web: Option<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub deleted: Option<bool>,
#[serde(default, flatten)]
pub extensions: serde_json::Map<String, serde_json::Value>,
}
#[cfg(test)]
mod serde_tests {
use pretty_assertions::assert_eq;
use serde_json::json;
use time::macros::datetime;
use super::System;
use crate::{OParlVersion, namespace::SystemNamespaceUrl};
fn example_system() -> System {
System {
id: "https://oparl.example.org/"
.parse()
.expect("value must be parseable as id"),
namespace: SystemNamespaceUrl::Identifier,
oparl_version: OParlVersion::Version1_1,
other_oparl_versions: vec![
"https://oparl2.example.org/"
.parse()
.expect("value must be parseable as url"),
],
license: None,
body: "https://oparl.example.org/bodies"
.parse()
.expect("value must be parseable as url"),
name: Some(
"Beispiel-System"
.parse()
.expect("value must be parseable as name"),
),
contact_email: Some(
"info@example.org"
.parse()
.expect("value must be parseable as email"),
),
contact_name: Some(
"Allgemeiner OParl Kontakt"
.parse()
.expect("value must be parseable as name"),
),
website: Some(
"http://www.example.org/"
.parse()
.expect("value must be parseable as url"),
),
vendor: Some(
"http://example-software.com/"
.parse()
.expect("value must be parseable as url"),
),
product: Some(
"http://example-software.com/oparl-server/"
.parse()
.expect("value must be parseable as url"),
),
created: datetime!(2011-11-11 11:11:00 +01:00).into(),
modified: datetime!(2012-11-11 11:11:00 +01:00).into(),
web: None,
deleted: None,
extensions: serde_json::Map::new(),
}
}
fn example_system_json() -> serde_json::Value {
json!({
"id": "https://oparl.example.org/",
"type": "https://schema.oparl.org/1.1/System",
"oparlVersion": "https://schema.oparl.org/1.1/",
"body": "https://oparl.example.org/bodies",
"name": "Beispiel-System",
"contactEmail": "info@example.org",
"contactName": "Allgemeiner OParl Kontakt",
"website": "http://www.example.org/",
"vendor": "http://example-software.com/",
"product": "http://example-software.com/oparl-server/",
"otherOparlVersions": [
"https://oparl2.example.org/"
],
"created": "2011-11-11T11:11:00+01:00",
"modified": "2012-11-11T11:11:00+01:00"
})
}
#[test]
fn serialize() {
assert_eq!(json!(example_system()), example_system_json());
}
#[test]
fn serialize_with_extensions() {
let extensions = json!({"pib:hello":"world", "pib:status":"new"})
.as_object()
.cloned()
.unwrap();
let mut example_system = example_system();
example_system.extensions = extensions;
let mut example_system_json = example_system_json();
{
let extensions = example_system_json.as_object_mut().unwrap();
extensions.insert("pib:hello".into(), "world".into());
extensions.insert("pib:status".into(), "new".into());
}
assert_eq!(json!(example_system), example_system_json);
}
#[test]
fn deserialize_good() {
let deserialized: System = serde_json::from_value(example_system_json())
.expect("value must be deserializable as System");
assert_eq!(deserialized, example_system());
}
#[test]
fn deserialize_with_extensions() {
let extensions = json!({"pib:hello":"world", "pib:status":"new"})
.as_object()
.cloned()
.unwrap();
let mut example_system = example_system();
example_system.extensions = extensions;
let mut example_system_json = example_system_json();
{
let extensions = example_system_json.as_object_mut().unwrap();
extensions.insert("pib:hello".into(), "world".into());
extensions.insert("pib:status".into(), "new".into());
}
let deserialized: System = serde_json::from_value(example_system_json)
.expect("value must be deserializable as System");
assert_eq!(deserialized, example_system);
assert_eq!(deserialized.extensions.len(), 2);
assert_eq!(deserialized.extensions["pib:hello"], "world");
assert_eq!(deserialized.extensions["pib:status"], "new");
}
#[test]
fn deserialize_bad() {
assert!(serde_json::from_value::<System>(json!("xyzabcd")).is_err());
assert!(serde_json::from_value::<System>(json!(true)).is_err());
assert!(serde_json::from_value::<System>(json!(123)).is_err());
}
}