1use url::Url;
7
8use crate::{
9 namespace::PersonNamespaceUrl, BodyId, DateTime, EmailAddress, Keyword, Location, LocationId,
10 Membership, Name, PersonId,
11};
12
13#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct Person {
16 pub id: PersonId,
17
18 #[serde(rename = "type")]
19 pub namespace: PersonNamespaceUrl,
20
21 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub body: Option<BodyId>,
23
24 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub name: Option<Name>,
26
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub family_name: Option<Name>,
29
30 #[serde(default, skip_serializing_if = "Option::is_none")]
31 pub given_name: Option<Name>,
32
33 #[serde(default, skip_serializing_if = "Option::is_none")]
34 pub form_of_address: Option<String>,
35
36 #[serde(default, skip_serializing_if = "Option::is_none")]
37 pub affix: Option<String>,
38
39 #[serde(default, skip_serializing_if = "Vec::is_empty")]
40 pub title: Vec<String>,
41
42 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub gender: Option<String>,
44
45 #[serde(default, skip_serializing_if = "Vec::is_empty")]
46 pub phone: Vec<String>,
47
48 #[serde(default, skip_serializing_if = "Vec::is_empty")]
49 pub email: Vec<EmailAddress>,
50
51 #[serde(default, skip_serializing_if = "Option::is_none")]
52 pub location: Option<LocationId>,
53
54 #[serde(default, skip_serializing_if = "Option::is_none")]
55 pub location_object: Option<Location>,
56
57 #[serde(default, skip_serializing_if = "Vec::is_empty")]
58 pub status: Vec<String>,
59
60 #[serde(default, skip_serializing_if = "Vec::is_empty")]
61 pub membership: Vec<Membership>,
62
63 #[serde(default, skip_serializing_if = "Option::is_none")]
64 pub life: Option<String>,
65
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 pub life_source: Option<String>,
68
69 #[serde(default, skip_serializing_if = "Option::is_none")]
70 pub license: Option<Url>,
71
72 #[serde(default, skip_serializing_if = "Vec::is_empty")]
73 pub keyword: Vec<Keyword>,
74
75 pub created: DateTime,
76
77 pub modified: DateTime,
78
79 #[serde(default, skip_serializing_if = "Option::is_none")]
80 pub web: Option<Url>,
81
82 #[serde(default, skip_serializing_if = "Option::is_none")]
83 pub deleted: Option<bool>,
84}
85
86#[cfg(test)]
87mod serde_tests {
88 use super::Person;
89 use crate::{
90 namespace::{MembershipNamespaceUrl, PersonNamespaceUrl},
91 Membership,
92 };
93
94 use pretty_assertions::assert_eq;
95 use serde_json::json;
96 use time::macros::{date, datetime};
97
98 fn example_person() -> Person {
99 Person {
100 id: "https://oparl.example.org/person/29"
101 .parse()
102 .expect("value must be parseable as id"),
103 namespace: PersonNamespaceUrl::Identifier,
104 body: Some(
105 "https://oparl.example.org/body/0"
106 .parse()
107 .expect("value must be parseable as url"),
108 ),
109 name: Some("Prof. Dr. Max Mustermann".into()),
110 family_name: Some("Mustermann".into()),
111 given_name: Some("Max".into()),
112 form_of_address: Some("Ratsfrau".into()),
113 affix: None,
114 title: vec!["Prof.".into(), "Dr.".into()],
115 gender: Some("male".into()),
116 email: vec!["max@mustermann.de"
117 .parse()
118 .expect("value must be parseable as email")],
119 phone: vec!["+493012345678".into()],
120 location: None,
121 location_object: None,
122 status: vec!["Bezirksbürgermeister".into()],
123 membership: vec![
124 Membership {
125 id: "https://oparl.example.org/memberships/385"
126 .parse()
127 .expect("value must be parseable as id"),
128 namespace: MembershipNamespaceUrl::Identifier,
129 person: None,
130 organization: Some(
131 "https://oparl.example.org/organizations/5"
132 .parse()
133 .expect("value must be parseable as url"),
134 ),
135 role: Some("Vorsitzende".into()),
136 voting_right: Some(true),
137 start_date: Some(date!(2013 - 12 - 03).into()),
138 end_date: None,
139 on_behalf_of: None,
140 license: None,
141 keyword: vec![],
142 created: datetime!(2011-11-11 11:11:00 +01:00).into(),
143 modified: datetime!(2012-08-16 14:05:27 +02:00).into(),
144 web: None,
145 deleted: None,
146 },
147 Membership {
148 id: "https://oparl.example.org/memberships/693"
149 .parse()
150 .expect("value must be parseable as id"),
151 namespace: MembershipNamespaceUrl::Identifier,
152 person: None,
153 organization: Some(
154 "https://oparl.example.org/organizations/9"
155 .parse()
156 .expect("value must be parseable as url"),
157 ),
158 role: Some("Sachkundige Bürgerin".into()),
159 voting_right: Some(false),
160 start_date: Some(date!(2013 - 12 - 03).into()),
161 end_date: Some(date!(2014 - 07 - 28).into()),
162 on_behalf_of: None,
163 license: None,
164 keyword: vec![],
165 created: datetime!(2011-11-11 11:11:00 +01:00).into(),
166 modified: datetime!(2012-08-16 14:05:27 +02:00).into(),
167 web: None,
168 deleted: None,
169 },
170 ],
171 life: None,
172 life_source: None,
173 license: None,
174 keyword: vec![],
175 created: datetime!(2011-11-11 11:11:00 +01:00).into(),
176 modified: datetime!(2012-08-16 14:05:27 +02:00).into(),
177 web: None,
178 deleted: None,
179 }
180 }
181
182 fn example_person_json() -> serde_json::Value {
183 json!({
184 "id": "https://oparl.example.org/person/29",
185 "type": "https://schema.oparl.org/1.1/Person",
186 "body": "https://oparl.example.org/body/0",
187 "name": "Prof. Dr. Max Mustermann",
188 "familyName": "Mustermann",
189 "givenName": "Max",
190 "title": [
191 "Prof.",
192 "Dr."
193 ],
194 "formOfAddress": "Ratsfrau",
195 "gender": "male",
196 "email": [
197 "max@mustermann.de"
198 ],
199 "phone": [
200 "+493012345678"
201 ],
202 "status": [
203 "Bezirksbürgermeister"
204 ],
205 "membership": [
206 {
207 "id": "https://oparl.example.org/memberships/385",
208 "type": "https://schema.oparl.org/1.1/Membership",
209 "organization": "https://oparl.example.org/organizations/5",
210 "role": "Vorsitzende",
211 "votingRight": true,
212 "startDate": "2013-12-03",
213 "created": "2011-11-11T11:11:00+01:00",
214 "modified": "2012-08-16T14:05:27+02:00"
215 },
216 {
217 "id": "https://oparl.example.org/memberships/693",
218 "type": "https://schema.oparl.org/1.1/Membership",
219 "organization": "https://oparl.example.org/organizations/9",
220 "role": "Sachkundige Bürgerin",
221 "votingRight": false,
222 "startDate": "2013-12-03",
223 "endDate": "2014-07-28",
224 "created": "2011-11-11T11:11:00+01:00",
225 "modified": "2012-08-16T14:05:27+02:00"
226 }
227 ],
228 "created": "2011-11-11T11:11:00+01:00",
229 "modified": "2012-08-16T14:05:27+02:00"
230 })
231 }
232
233 #[test]
234 fn serialize() {
235 assert_eq!(json!(example_person()), example_person_json());
236 }
237
238 #[test]
239 fn deserialize_good() {
240 let deserialized: Person = serde_json::from_value(example_person_json())
241 .expect("value must be deserializable as Person");
242 assert_eq!(deserialized, example_person());
243 }
244
245 #[test]
246 fn deserialize_bad() {
247 assert!(serde_json::from_value::<Person>(json!("xyzabcd")).is_err());
248 assert!(serde_json::from_value::<Person>(json!(true)).is_err());
249 assert!(serde_json::from_value::<Person>(json!(123)).is_err());
250 }
251}