gedcom-x 0.5.1__py3-none-any.whl → 0.5.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
gedcomx/Name.py CHANGED
@@ -1,12 +1,14 @@
1
1
  from enum import Enum
2
2
  from typing import List,Optional
3
+ from typing_extensions import Self
3
4
 
4
5
  from .Attribution import Attribution
5
6
  from .Conclusion import Conclusion, ConfidenceLevel
6
7
  from .Date import Date
7
8
  from .Note import Note
9
+ from .Serialization import Serialization
8
10
  from .SourceReference import SourceReference
9
- from .URI import URI
11
+ from .Resource import Resource
10
12
 
11
13
 
12
14
  class NameType(Enum):
@@ -99,10 +101,11 @@ class NamePart:
99
101
  self.value = value
100
102
  self.qualifiers = qualifiers
101
103
 
102
- def _prop_dict(self):
103
- return {'type': self.type.value if self.type else None,
104
- 'value': self.value if self.value else None,
105
- 'qualifiers': [qualifier.value for qualifier in self.qualifiers]}
104
+ def _as_dict_(self):
105
+ return Serialization.serialize_dict(
106
+ {'type': self.type.value if self.type else None,
107
+ 'value': self.value if self.value else None,
108
+ 'qualifiers': [qualifier.value for qualifier in self.qualifiers] if self.qualifiers else None})
106
109
 
107
110
  def __eq__(self, other):
108
111
  if not isinstance(other, NamePart):
@@ -120,10 +123,12 @@ class NameForm:
120
123
  self.fullText = fullText
121
124
  self.parts = parts
122
125
 
123
- def _prop_dict(self):
124
- return {'lang': self.lang,
125
- 'fullText': self.fullText,
126
- 'parts': [part._prop_dict() for part in self.parts]}
126
+ @property
127
+ def _as_dict_(self):
128
+ return Serialization.serialize_dict(
129
+ {'lang': self.lang,
130
+ 'fullText': self.fullText,
131
+ 'parts': [part._as_dict_() for part in self.parts] if self.parts else None})
127
132
 
128
133
  def _fulltext_parts(self):
129
134
  pass
@@ -137,37 +142,40 @@ class Name(Conclusion):
137
142
  """
138
143
  Takes a string and returns a GedcomX Name Object
139
144
  """
140
- text = text.replace("/","")
141
- parts = text.rsplit(' ', 1)
142
-
143
- # Assign val1 and val2 based on the split
144
- given = parts[0] if len(parts) > 1 else ""
145
- surname = parts[1] if len(parts) > 1 else parts[0]
145
+ if text:
146
+ text = text.replace("/","")
147
+ parts = text.rsplit(' ', 1)
146
148
 
147
- # Remove any '/' characters from both val1 and val2
148
- #given = given.replace('/', '')
149
- #surname = surname.replace('/', '')
149
+ # Assign val1 and val2 based on the split
150
+ given = parts[0] if len(parts) > 1 else ""
151
+ surname = parts[1] if len(parts) > 1 else parts[0]
152
+
153
+ # Remove any '/' characters from both val1 and val2
154
+ #given = given.replace('/', '')
155
+ #surname = surname.replace('/', '')
150
156
 
151
- given_name_part = NamePart(type = NamePartType.Given, value=given)
152
- surname_part = NamePart(type = NamePartType.Surname, value=surname)
157
+ given_name_part = NamePart(type = NamePartType.Given, value=given)
158
+ surname_part = NamePart(type = NamePartType.Surname, value=surname)
153
159
 
154
- name_form = NameForm(fullText=text,parts=[given_name_part,surname_part])
155
- name = Name(type=NameType.BirthName,nameForms=[name_form])
160
+ name_form = NameForm(fullText=text,parts=[given_name_part,surname_part])
161
+ name = Name(type=NameType.BirthName,nameForms=[name_form])
162
+ else:
163
+ name = Name()
156
164
  return name
157
165
 
158
166
  def __init__(self, id: str = None,
159
167
  lang: str = 'en',
160
- sources: Optional[List[SourceReference]] = [],
161
- analysis: URI = None,
162
- notes: Optional[List[Note]] = [],
163
- confidence: ConfidenceLevel = None,
164
- attribution: Attribution = None,
168
+ sources: Optional[List[SourceReference]] = None,
169
+ analysis: Resource = None,
170
+ notes: Optional[List[Note]] = None,
171
+ confidence: Optional[ConfidenceLevel] = None,
172
+ attribution: Optional[Attribution] = None,
165
173
  type: Optional[NameType] = None,
166
- nameForms: NameForm = [],
174
+ nameForms: Optional[List[NameForm]]= None,
167
175
  date: Optional[Date] = None) -> None:
168
176
  super().__init__(id, lang, sources, analysis, notes, confidence, attribution)
169
177
  self.type = type
170
- self.nameForms = nameForms
178
+ self.nameForms = nameForms if nameForms else []
171
179
  self.date = date
172
180
 
173
181
  def _add_name_part(self, namepart_to_add: NamePart):
@@ -179,13 +187,45 @@ class Name(Conclusion):
179
187
 
180
188
  @property
181
189
  def _as_dict_(self):
190
+ def _serialize(value):
191
+ if isinstance(value, (str, int, float, bool, type(None))):
192
+ return value
193
+ elif isinstance(value, dict):
194
+ return {k: _serialize(v) for k, v in value.items()}
195
+ elif isinstance(value, (list, tuple, set)):
196
+ return [_serialize(v) for v in value]
197
+ elif hasattr(value, "_as_dict_"):
198
+ return value._as_dict_
199
+ else:
200
+ return str(value) # fallback for unknown objects
201
+
182
202
  name_as_dict = super()._as_dict_
203
+
183
204
  name_as_dict.update( {
184
205
  'type':self.type.value if self.type else None,
185
- 'nameForms': [nameForm._prop_dict() for nameForm in self.nameForms],
186
- 'date': self.date._prop_date() if self.date else None})
206
+ 'nameForms': [nameForm._as_dict_ for nameForm in self.nameForms],
207
+ 'date': self.date._as_dict_ if self.date else None})
208
+
209
+ #del name_as_dict['id']
210
+ # Serialize and exclude None values
211
+ for key, value in name_as_dict.items():
212
+ if value is not None:
213
+ name_as_dict[key] = _serialize(value)
214
+
215
+ # 3) merge and filter out None *at the top level*
216
+ return {
217
+ k: v
218
+ for k, v in name_as_dict.items()
219
+ if v is not None
220
+ }
221
+
187
222
  return name_as_dict
188
223
 
224
+ class QuickName():
225
+ def __new__(cls,name: str) -> Name:
226
+ obj = Name(nameForms=[NameForm(fullText=name)])
227
+ return obj
228
+
189
229
  def ensure_list(val):
190
230
  if val is None:
191
231
  return []
@@ -223,7 +263,7 @@ Name._from_json_ = classmethod(lambda cls, data: cls(
223
263
  id=data.get('id'),
224
264
  lang=data.get('lang', 'en'),
225
265
  sources=[SourceReference._from_json_(s) for s in ensure_list(data.get('sources'))],
226
- analysis=URI._from_json_(data['analysis']) if data.get('analysis') else None,
266
+ analysis=Resource._from_json_(data['analysis']) if data.get('analysis') else None,
227
267
  notes=[Note._from_json_(n) for n in ensure_list(data.get('notes'))],
228
268
  confidence=ConfidenceLevel._from_json_(data['confidence']) if data.get('confidence') else None,
229
269
  attribution=Attribution._from_json_(data['attribution']) if data.get('attribution') else None,
@@ -232,10 +272,5 @@ Name._from_json_ = classmethod(lambda cls, data: cls(
232
272
  date=Date._from_json_(data['date']) if data.get('date') else None
233
273
  ))
234
274
 
235
- Name._to_dict_ = lambda self: {
236
- **self._as_dict_,
237
- 'type': self.type.value if self.type else None,
238
- 'nameForms': [nf._to_dict_() for nf in self.nameForms] if self.nameForms else [],
239
- 'date': self.date._prop_date() if self.date else None
240
- }
275
+
241
276
 
gedcomx/Note.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from typing import Optional
2
2
 
3
3
  from .Attribution import Attribution
4
+ from .Serialization import Serialization
4
5
 
5
6
  class Note:
6
7
  identifier = 'http://gedcomx.org/v1/Note'
@@ -10,24 +11,24 @@ class Note:
10
11
  self.lang = lang
11
12
  self.subject = subject
12
13
  self.text = text
13
- self.attribution = attribution
14
-
15
-
14
+ self.attribution = attribution
16
15
 
17
16
  def append(self, text_to_add: str):
18
17
  if text_to_add and isinstance(text_to_add, str):
19
18
  self.text = self.text + text_to_add
20
19
  else:
20
+ return #TODO
21
21
  raise ValueError("The text to add must be a non-empty string.")
22
22
 
23
23
  @property
24
24
  def _as_dict_(self):
25
- return {
25
+ note_dict = {
26
26
  "lang":self.lang if self.lang else None,
27
27
  "subject":self.subject if self.subject else None,
28
28
  "text":self.text if self.text else None,
29
29
  "attribution": self.attribution if self.attribution else None
30
30
  }
31
+ return Serialization.serialize_dict(note_dict)
31
32
 
32
33
  def __eq__(self, other):
33
34
  if not isinstance(other, Note):
gedcomx/OnlineAccount.py CHANGED
@@ -1,10 +1,10 @@
1
1
  from typing import Optional
2
2
 
3
- from .URI import URI
3
+ from .Resource import Resource
4
4
 
5
5
  class OnlineAccount:
6
6
  identifier = 'http://gedcomx.org/v1/OnlineAccount'
7
7
  version = 'http://gedcomx.org/conceptual-model/v1'
8
8
 
9
- def __init__(self, serviceHomepage: URI, accountName: str) -> None:
9
+ def __init__(self, serviceHomepage: Resource, accountName: str) -> None:
10
10
  pass
gedcomx/Person.py CHANGED
@@ -1,40 +1,58 @@
1
1
  from enum import Enum
2
2
  from typing import List, Optional
3
+ from urllib.parse import urljoin
3
4
 
4
5
  from .Attribution import Attribution
5
6
  from .Conclusion import ConfidenceLevel
7
+ from .Date import Date
6
8
  from .EvidenceReference import EvidenceReference
7
- from .Fact import Fact
9
+ from .Fact import Fact, FactType
8
10
  from .Gender import Gender, GenderType
9
- from .Identifier import Identifier
10
- from .Name import Name, NameForm, NamePart, NamePartType, NamePartQualifier
11
+ from .Identifier import IdentifierList
12
+ from .Name import Name, QuickName
11
13
  from .Note import Note
12
14
  from .SourceReference import SourceReference
15
+ from .Serialization import Serialization
13
16
  from .Subject import Subject
14
- from .URI import URI
17
+ from .Resource import Resource
18
+ from collections.abc import Sized
19
+ from .Extensions.rs10.rsLink import _rsLinkList
15
20
 
16
21
  class Person(Subject):
22
+ """A person in the system.
23
+
24
+ Args:
25
+ id (str): Unique identifier for this person.
26
+ name (str): Full name.
27
+ birth (date): Birth date (YYYY-MM-DD).
28
+ friends (List[Person], optional): List of friends. Defaults to None.
29
+
30
+ Raises:
31
+ ValueError: If `id` is not a valid UUID.
32
+ """
17
33
  identifier = 'http://gedcomx.org/v1/Person'
18
34
  version = 'http://gedcomx.org/conceptual-model/v1'
19
35
 
20
- def __init__(self, id: str = None,
36
+ def __init__(self, id: str | None = None,
21
37
  lang: str = 'en',
22
38
  sources: Optional[List[SourceReference]] = None,
23
- analysis: Optional[URI] = None,
39
+ analysis: Optional[Resource] = None,
24
40
  notes: Optional[List[Note]] = None,
25
41
  confidence: Optional[ConfidenceLevel] = None,
26
42
  attribution: Optional[Attribution] = None,
27
43
  extracted: bool = None,
28
44
  evidence: Optional[List[EvidenceReference]] = None,
29
45
  media: Optional[List[SourceReference]] = None,
30
- identifiers: Optional[List[Identifier]] = None,
46
+ identifiers: Optional[IdentifierList] = None,
31
47
  private: Optional[bool] = False,
32
48
  gender: Optional[Gender] = Gender(type=GenderType.Unknown),
33
49
  names: Optional[List[Name]] = None,
34
50
  facts: Optional[List[Fact]] = None,
35
- living: Optional[bool] = False) -> None:
51
+ living: Optional[bool] = False,
52
+ links: Optional[_rsLinkList] = None,
53
+ uri: Optional[Resource] = None) -> None:
36
54
  # Call superclass initializer if needed
37
- super().__init__(id, lang, sources, analysis, notes, confidence, attribution, extracted, evidence, media, identifiers)
55
+ super().__init__(id, lang, sources, analysis, notes, confidence, attribution, extracted, evidence, media, identifiers,links=links,uri=uri)
38
56
 
39
57
  # Initialize mutable attributes to empty lists if None
40
58
  self.sources = sources if sources is not None else []
@@ -51,8 +69,7 @@ class Person(Subject):
51
69
  self.living = living #TODO This is from familysearch API
52
70
 
53
71
  self._relationships = []
54
-
55
-
72
+
56
73
  def add_fact(self, fact_to_add: Fact) -> bool:
57
74
  if fact_to_add and isinstance(fact_to_add,Fact):
58
75
  for current_fact in self.facts:
@@ -80,99 +97,96 @@ class Person(Subject):
80
97
  else:
81
98
  raise ValueError()
82
99
 
100
+ def display(self):
101
+ display = {
102
+ "ascendancyNumber": "1",
103
+ "deathDate": "from 2001 to 2005",
104
+ "descendancyNumber": "1",
105
+ "gender": self.gender.type,
106
+ "lifespan": "-2005",
107
+ "name": self.names[0].nameForms[0].fullText
108
+ }
109
+
110
+ return display
111
+
83
112
  @property
84
113
  def _as_dict_(self):
85
- def _serialize(value):
86
- if isinstance(value, (str, int, float, bool, type(None))):
87
- return value
88
- elif isinstance(value, dict):
89
- return {k: _serialize(v) for k, v in value.items()}
90
- elif isinstance(value, (list, tuple, set)):
91
- return [_serialize(v) for v in value]
92
- elif hasattr(value, "_as_dict_"):
93
- return value._as_dict_
94
- else:
95
- return str(value) # fallback for unknown objects
96
-
97
- subject_fields = super()._as_dict_ # Start with base class fields
114
+ type_as_dict = super()._as_dict_ # Start with base class fields
98
115
  # Only add Relationship-specific fields
99
- subject_fields.update({
116
+ type_as_dict.update({
100
117
  'private': self.private,
101
118
  'living': self.living,
102
- 'gender': self.gender.type.value if self.gender.type else None,
103
- 'names': [name for name in self.names],
104
- 'facts': [fact for fact in self.facts]
119
+ 'gender': self.gender._as_dict_ if self.gender else None,
120
+ 'names': [name._as_dict_ for name in self.names],
121
+ 'facts': [fact._as_dict_ for fact in self.facts],
122
+ 'uri': self.uri._as_dict_ if self.uri else None
105
123
 
106
124
  })
107
125
 
108
- # Serialize and exclude None values
109
- for key, value in subject_fields.items():
110
- if value is not None:
111
- subject_fields[key] = _serialize(value)
112
-
113
- return subject_fields
114
-
115
-
126
+ return Serialization.serialize_dict(type_as_dict)
127
+
116
128
  @classmethod
117
129
  def _from_json_(cls, data: dict):
118
130
  """
119
131
  Create a Person instance from a JSON-dict (already parsed).
120
132
  """
121
- def ensure_list(value):
122
- if value is None:
123
- return []
124
- if isinstance(value, list):
125
- return value
126
- return [value] # wrap single item in list
127
-
128
- # Basic scalar fields
129
- id_ = data.get('id')
130
- lang = data.get('lang', 'en')
131
- private = data.get('private', False)
132
- extracted = data.get('extracted', False)
133
-
134
- living = data.get('extracted', False)
135
-
136
- # Complex singletons
137
- analysis = URI._from_json_(data['analysis']) if data.get('analysis') else None
138
- attribution = Attribution._from_json_(data['attribution']) if data.get('attribution') else None
139
- confidence = ConfidenceLevel._from_json_(data['confidence']) if data.get('confidence') else None
140
-
141
- # Gender (string or dict depending on your JSON)
142
- gender_json = data.get('gender')
143
- if isinstance(gender_json, dict):
144
- gender = Gender._from_json_(gender_json)
145
- else:
146
- # if it's just the enum value
147
- gender = Gender(type=GenderType(gender_json)) if gender_json else Gender(type=GenderType.Unknown)
133
+ return Serialization.deserialize(data, Person)
134
+
135
+ @classmethod
136
+ def from_familysearch(cls, pid: str, token: str, *, base_url: Optional[str] = None):
137
+ """
138
+ Fetch a single person by PID from FamilySearch and return a Person.
139
+ - pid: e.g. "KPHP-4B4"
140
+ - token: OAuth2 access token (Bearer)
141
+ - base_url: override API base (defaults to settings.FS_API_BASE or prod)
142
+ """
143
+ import requests
144
+ default_base = "https://apibeta.familysearch.org/platform/"
145
+
146
+ base = (base_url or default_base).rstrip("/") + "/"
147
+ url = urljoin(base, f"tree/persons/{pid}")
148
+
149
+ headers = {
150
+ "Accept": "application/json",
151
+ "Authorization": f"Bearer {token}",
152
+ }
153
+
154
+ resp = requests.get(url, headers=headers, timeout=(5, 30))
155
+ resp.raise_for_status()
156
+
157
+ payload = resp.json()
158
+ persons = payload.get("persons") or []
159
+
160
+ # Prefer exact match on PID, else first item if present
161
+ person_json = next((p for p in persons if (p.get("id") == pid)), None) or (persons[0] if persons else None)
162
+ if not person_json:
163
+ raise ValueError(f"FamilySearch returned no person for PID {pid}")
164
+
165
+ # Keep your existing deserialization helper
166
+ return Serialization.deserialize(person_json, Person)
167
+
168
+ class QuickPerson:
169
+ """A GedcomX Person Data Type created with basic information.
170
+
171
+ Underlying GedcomX Types are created for you.
148
172
 
173
+ Args:
174
+ name (str): Full name.
175
+ birth (date,Optional): Birth date (YYYY-MM-DD).
176
+ death (date, Optional)
177
+
149
178
 
150
- sources = [SourceReference._from_json_(o) for o in ensure_list(data.get('sources'))]
151
- notes = [Note._from_json_(o) for o in ensure_list(data.get('notes'))]
152
- evidence = [EvidenceReference._from_json_(o) for o in ensure_list(data.get('evidence'))]
153
- media = [SourceReference._from_json_(o) for o in ensure_list(data.get('media'))]
154
- identifiers = [Identifier._from_json_(o) for o in ensure_list(data.get('identifiers'))]
155
- names = [Name._from_json_(o) for o in ensure_list(data.get('names'))]
156
- facts = [Fact._from_json_(o) for o in ensure_list(data.get('facts'))]
157
-
158
- # Build the instance
159
- inst = cls(
160
- id = id_,
161
- lang = lang,
162
- sources = sources,
163
- analysis = analysis,
164
- notes = notes,
165
- confidence = confidence,
166
- attribution = attribution,
167
- extracted = extracted,
168
- evidence = evidence,
169
- media = media,
170
- identifiers = identifiers,
171
- private = private,
172
- gender = gender,
173
- names = names,
174
- facts = facts,
175
- living = living
176
- )
177
-
178
- return inst
179
+
180
+ Raises:
181
+ ValueError: If `id` is not a valid UUID.
182
+ """
183
+ def __new__(cls, name: str, dob: Optional[str] = None, dod: Optional[str] = None):
184
+ # Build facts from args
185
+ facts = []
186
+ if dob:
187
+ facts.append(Fact(type=FactType.Birth, date=Date(original=dob)))
188
+ if dod:
189
+ facts.append(Fact(type=FactType.Death, date=Date(original=dod)))
190
+
191
+ # Return the different class instance
192
+ return Person(facts=facts, names=[QuickName(name=name)] if name else None)
@@ -4,36 +4,39 @@ from .Attribution import Attribution
4
4
  from .Conclusion import ConfidenceLevel
5
5
  from .Date import Date
6
6
  from .EvidenceReference import EvidenceReference
7
- from .Identifier import Identifier
7
+ from .Identifier import IdentifierList
8
8
  from .Note import Note
9
9
  from .SourceReference import SourceReference
10
10
  from .TextValue import TextValue
11
- from .URI import URI
12
-
11
+ from .Resource import Resource
12
+ from .Serialization import Serialization
13
13
  from .Subject import Subject
14
+ from .URI import URI
14
15
 
15
16
  class PlaceDescription(Subject):
16
17
  identifier = "http://gedcomx.org/v1/PlaceDescription"
17
18
  version = 'http://gedcomx.org/conceptual-model/v1'
18
19
 
19
- def __init__(self, id: str =None,
20
+ def __init__(self, id: Optional[str] =None,
20
21
  lang: str = 'en',
21
- sources: Optional[List[SourceReference]] = [],
22
- analysis: URI = None, notes: Optional[List[Note]] =[],
23
- confidence: ConfidenceLevel = None,
24
- attribution: Attribution = None,
25
- extracted: bool = None,
26
- evidence: List[EvidenceReference] = None,
27
- media: List[SourceReference] = [],
28
- identifiers: List[Identifier] = [],
29
- names: List[TextValue] = [],
22
+ sources: Optional[List[SourceReference]] = None,
23
+ analysis: Optional[Resource] = None,
24
+ notes: Optional[List[Note]] =None,
25
+ confidence: Optional[ConfidenceLevel] = None,
26
+ attribution: Optional[Attribution] = None,
27
+ extracted: Optional[bool] = None,
28
+ evidence: Optional[List[EvidenceReference]] = None,
29
+ media: Optional[List[SourceReference]] = None,
30
+ identifiers: Optional[IdentifierList] = None,
31
+ names: Optional[List[TextValue]] = None,
30
32
  type: Optional[str] = None,
31
33
  place: Optional[URI] = None,
32
- jurisdiction: Optional["PlaceDescription"] = None, # PlaceDescription
34
+ jurisdiction: Optional["Resource | PlaceDescription"] = None, # PlaceDescription
33
35
  latitude: Optional[float] = None,
34
36
  longitude: Optional[float] = None,
35
37
  temporalDescription: Optional[Date] = None,
36
- spatialDescription: Optional[URI] = None,) -> None:
38
+ spatialDescription: Optional[Resource] = None,) -> None:
39
+
37
40
  super().__init__(id, lang, sources, analysis, notes, confidence, attribution, extracted, evidence, media, identifiers)
38
41
  self.names = names
39
42
  self.type = type
@@ -44,4 +47,24 @@ class PlaceDescription(Subject):
44
47
  self.temporalDescription = temporalDescription
45
48
  self.spacialDescription = spatialDescription
46
49
 
47
-
50
+ @property
51
+ def _as_dict_(self):
52
+ type_as_dict = super()._as_dict_
53
+ type_as_dict.update({
54
+ "names": [n for n in self.names] if self.names else None,
55
+ "type": self.type if self.type else None,
56
+ "place": self.place._as_dict_ if self.place else None,
57
+ "jurisdiction": self.jurisdiction._as_dict_ if self.jurisdiction else None,
58
+ "latitude": float(self.latitide) if self.latitide else None,
59
+ "longitude": float(self.longitute) if self.longitute else None,
60
+ "temporalDescription": self.temporalDescription if self.temporalDescription else None,
61
+ "spatialDescription": self.spacialDescription._as_dict_ if self.spacialDescription else None
62
+ })
63
+ return Serialization.serialize_dict(type_as_dict)
64
+
65
+ @classmethod
66
+ def _from_json_(cls, data: dict):
67
+ """
68
+ Create a PlaceDescription instance from a JSON-dict (already parsed).
69
+ """
70
+ return Serialization.deserialize(data, PlaceDescription)
gedcomx/PlaceReference.py CHANGED
@@ -1,31 +1,30 @@
1
1
  from typing import Optional
2
2
 
3
- from .URI import URI
3
+ from .Resource import Resource
4
+ from .Serialization import Serialization
4
5
 
5
6
  class PlaceReference:
6
7
  identifier = 'http://gedcomx.org/v1/PlaceReference'
7
8
  version = 'http://gedcomx.org/conceptual-model/v1'
8
9
 
9
- def __init__(self, original: Optional[str], descriptionRef: Optional[URI]) -> None:
10
+ def __init__(self,
11
+ original: Optional[str] = None,
12
+ description: Optional[Resource] = None) -> None:
10
13
  self.original = original
11
- self.descriptionRef = descriptionRef
14
+ self.description = description
12
15
 
13
16
  @property
14
17
  def _as_dict_(self):
15
- return {
18
+ type_as_dict = {
16
19
  'original': self.original,
17
- 'descriptionRef': self.descriptionRef._as_dict_ if self.descriptionRef else None
20
+ 'description': self.description._as_dict_ if self.description else None
18
21
  }
22
+ return Serialization.serialize_dict(type_as_dict)
23
+
24
+ @classmethod
25
+ def _from_json_(cls, data):
26
+
27
+ return Serialization.deserialize(data, PlaceReference)
19
28
 
20
- def ensure_list(val):
21
- if val is None:
22
- return []
23
- return val if isinstance(val, list) else [val]
24
29
 
25
- # PlaceReference
26
- PlaceReference._from_json_ = classmethod(lambda cls, data: PlaceReference(
27
- original=data.get('original'),
28
- descriptionRef=URI._from_json_(data['description']) if data.get('description') else None
29
- ))
30
30
 
31
-