use crate::{
BodyUrl, DateTime, EmailAddress, Keyword, Location, LocationUrl, Membership, Name, PersonUrl,
Url, namespace::PersonNamespaceUrl,
};
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Person {
pub id: PersonUrl,
#[serde(rename = "type")]
pub namespace: PersonNamespaceUrl,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub body: Option<BodyUrl>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub family_name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub given_name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub form_of_address: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub affix: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub title: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub gender: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub phone: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub email: Vec<EmailAddress>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub location: Option<LocationUrl>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub location_object: Option<Location>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub status: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub membership: Vec<Membership>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub life: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub life_source: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license: Option<Url>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub keyword: Vec<Keyword>,
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::{date, datetime};
use super::Person;
use crate::{
Membership,
namespace::{MembershipNamespaceUrl, PersonNamespaceUrl},
};
fn example_person() -> Person {
Person {
id: "https://oparl.example.org/person/29"
.parse()
.expect("value must be parseable as id"),
namespace: PersonNamespaceUrl::Identifier,
body: Some(
"https://oparl.example.org/body/0"
.parse()
.expect("value must be parseable as url"),
),
name: Some("Prof. Dr. Max Mustermann".into()),
family_name: Some("Mustermann".into()),
given_name: Some("Max".into()),
form_of_address: Some("Ratsfrau".into()),
affix: None,
title: vec!["Prof.".into(), "Dr.".into()],
gender: Some("male".into()),
email: vec![
"max@mustermann.de"
.parse()
.expect("value must be parseable as email"),
],
phone: vec!["+493012345678".into()],
location: None,
location_object: None,
status: vec!["Bezirksbürgermeister".into()],
membership: vec![
Membership {
id: "https://oparl.example.org/memberships/385"
.parse()
.expect("value must be parseable as id"),
namespace: MembershipNamespaceUrl::Identifier,
person: None,
organization: Some(
"https://oparl.example.org/organizations/5"
.parse()
.expect("value must be parseable as url"),
),
role: Some("Vorsitzende".into()),
voting_right: Some(true),
start_date: Some(date!(2013 - 12 - 03).into()),
end_date: None,
on_behalf_of: None,
license: None,
keyword: vec![],
created: datetime!(2011-11-11 11:11:00 +01:00).into(),
modified: datetime!(2012-08-16 14:05:27 +02:00).into(),
web: None,
deleted: None,
extensions: serde_json::Map::new(),
},
Membership {
id: "https://oparl.example.org/memberships/693"
.parse()
.expect("value must be parseable as id"),
namespace: MembershipNamespaceUrl::Identifier,
person: None,
organization: Some(
"https://oparl.example.org/organizations/9"
.parse()
.expect("value must be parseable as url"),
),
role: Some("Sachkundige Bürgerin".into()),
voting_right: Some(false),
start_date: Some(date!(2013 - 12 - 03).into()),
end_date: Some(date!(2014 - 07 - 28).into()),
on_behalf_of: None,
license: None,
keyword: vec![],
created: datetime!(2011-11-11 11:11:00 +01:00).into(),
modified: datetime!(2012-08-16 14:05:27 +02:00).into(),
web: None,
deleted: None,
extensions: serde_json::Map::new(),
},
],
life: None,
life_source: None,
license: None,
keyword: vec![],
created: datetime!(2011-11-11 11:11:00 +01:00).into(),
modified: datetime!(2012-08-16 14:05:27 +02:00).into(),
web: None,
deleted: None,
extensions: serde_json::Map::new(),
}
}
fn example_person_json() -> serde_json::Value {
json!({
"id": "https://oparl.example.org/person/29",
"type": "https://schema.oparl.org/1.1/Person",
"body": "https://oparl.example.org/body/0",
"name": "Prof. Dr. Max Mustermann",
"familyName": "Mustermann",
"givenName": "Max",
"title": [
"Prof.",
"Dr."
],
"formOfAddress": "Ratsfrau",
"gender": "male",
"email": [
"max@mustermann.de"
],
"phone": [
"+493012345678"
],
"status": [
"Bezirksbürgermeister"
],
"membership": [
{
"id": "https://oparl.example.org/memberships/385",
"type": "https://schema.oparl.org/1.1/Membership",
"organization": "https://oparl.example.org/organizations/5",
"role": "Vorsitzende",
"votingRight": true,
"startDate": "2013-12-03",
"created": "2011-11-11T11:11:00+01:00",
"modified": "2012-08-16T14:05:27+02:00"
},
{
"id": "https://oparl.example.org/memberships/693",
"type": "https://schema.oparl.org/1.1/Membership",
"organization": "https://oparl.example.org/organizations/9",
"role": "Sachkundige Bürgerin",
"votingRight": false,
"startDate": "2013-12-03",
"endDate": "2014-07-28",
"created": "2011-11-11T11:11:00+01:00",
"modified": "2012-08-16T14:05:27+02:00"
}
],
"created": "2011-11-11T11:11:00+01:00",
"modified": "2012-08-16T14:05:27+02:00"
})
}
#[test]
fn serialize() {
assert_eq!(json!(example_person()), example_person_json());
}
#[test]
fn deserialize_good() {
let deserialized: Person = serde_json::from_value(example_person_json())
.expect("value must be deserializable as Person");
assert_eq!(deserialized, example_person());
}
#[test]
fn deserialize_bad() {
assert!(serde_json::from_value::<Person>(json!("xyzabcd")).is_err());
assert!(serde_json::from_value::<Person>(json!(true)).is_err());
assert!(serde_json::from_value::<Person>(json!(123)).is_err());
}
}