lutaml-model 0.6.7 → 0.7.2
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.
- checksums.yaml +4 -4
- data/.github/workflows/dependent-repos-todo.json +7 -0
- data/.github/workflows/dependent-repos.json +17 -9
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +51 -65
- data/Gemfile +4 -1
- data/README.adoc +5083 -2612
- data/RELEASE_NOTES.adoc +346 -0
- data/docs/custom_adapters.adoc +144 -0
- data/lib/lutaml/model/attribute.rb +101 -16
- data/lib/lutaml/model/choice.rb +7 -0
- data/lib/lutaml/model/comparable_model.rb +48 -9
- data/lib/lutaml/model/config.rb +48 -42
- data/lib/lutaml/model/error/collection_count_out_of_range_error.rb +1 -1
- data/lib/lutaml/model/error/polymorphic_error.rb +14 -0
- data/lib/lutaml/model/error.rb +1 -0
- data/lib/lutaml/model/format_registry.rb +41 -0
- data/lib/lutaml/model/hash/document.rb +11 -0
- data/lib/lutaml/model/hash/mapping.rb +19 -0
- data/lib/lutaml/model/hash/mapping_rule.rb +9 -0
- data/lib/lutaml/model/hash/standard_adapter.rb +17 -0
- data/lib/lutaml/model/hash/transform.rb +8 -0
- data/lib/lutaml/model/hash.rb +21 -0
- data/lib/lutaml/model/json/document.rb +11 -0
- data/lib/lutaml/model/json/mapping.rb +19 -0
- data/lib/lutaml/model/json/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{json_adapter → json}/multi_json_adapter.rb +4 -5
- data/lib/lutaml/model/{json_adapter/standard_json_adapter.rb → json/standard_adapter.rb} +5 -3
- data/lib/lutaml/model/json/transform.rb +8 -0
- data/lib/lutaml/model/json.rb +21 -0
- data/lib/lutaml/model/key_value_document.rb +27 -0
- data/lib/lutaml/model/{key_value_mapping.rb → mapping/key_value_mapping.rb} +64 -16
- data/lib/lutaml/model/{key_value_mapping_rule.rb → mapping/key_value_mapping_rule.rb} +18 -2
- data/lib/lutaml/model/mapping/mapping.rb +13 -0
- data/lib/lutaml/model/mapping/mapping_rule.rb +300 -0
- data/lib/lutaml/model/schema/xml_compiler.rb +15 -15
- data/lib/lutaml/model/sequence.rb +2 -2
- data/lib/lutaml/model/serialization_adapter.rb +22 -0
- data/lib/lutaml/model/serialize.rb +219 -444
- data/lib/lutaml/model/services/logger.rb +54 -0
- data/lib/lutaml/model/services/transformer.rb +48 -0
- data/lib/lutaml/model/services.rb +2 -0
- data/lib/lutaml/model/toml/document.rb +11 -0
- data/lib/lutaml/model/toml/mapping.rb +27 -0
- data/lib/lutaml/model/toml/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{toml_adapter → toml}/toml_rb_adapter.rb +3 -3
- data/lib/lutaml/model/toml/tomlib_adapter.rb +19 -0
- data/lib/lutaml/model/toml/transform.rb +8 -0
- data/lib/lutaml/model/toml.rb +30 -0
- data/lib/lutaml/model/transform/key_value_transform.rb +291 -0
- data/lib/lutaml/model/transform/xml_transform.rb +239 -0
- data/lib/lutaml/model/transform.rb +78 -0
- data/lib/lutaml/model/type/date.rb +1 -1
- data/lib/lutaml/model/type/date_time.rb +2 -2
- data/lib/lutaml/model/type/hash.rb +1 -1
- data/lib/lutaml/model/type/time.rb +2 -2
- data/lib/lutaml/model/type/time_without_date.rb +2 -2
- data/lib/lutaml/model/type/value.rb +6 -9
- data/lib/lutaml/model/uninitialized_class.rb +64 -0
- data/lib/lutaml/model/utils.rb +44 -0
- data/lib/lutaml/model/validation.rb +1 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/builder/nokogiri.rb +2 -2
- data/lib/lutaml/model/{xml_adapter → xml}/builder/oga.rb +10 -10
- data/lib/lutaml/model/{xml_adapter → xml}/builder/ox.rb +1 -1
- data/lib/lutaml/model/{xml_adapter/xml_document.rb → xml/document.rb} +41 -21
- data/lib/lutaml/model/xml/element.rb +32 -0
- data/lib/lutaml/model/xml/mapping.rb +410 -0
- data/lib/lutaml/model/xml/mapping_rule.rb +141 -0
- data/lib/lutaml/model/xml/nokogiri_adapter.rb +232 -0
- data/lib/lutaml/model/{xml_adapter → xml}/oga/document.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/oga/element.rb +3 -1
- data/lib/lutaml/model/xml/oga_adapter.rb +171 -0
- data/lib/lutaml/model/xml/ox_adapter.rb +215 -0
- data/lib/lutaml/model/xml/transform.rb +8 -0
- data/lib/lutaml/model/{xml_adapter → xml}/xml_attribute.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/xml_element.rb +23 -10
- data/lib/lutaml/model/{xml_adapter → xml}/xml_namespace.rb +1 -1
- data/lib/lutaml/model/xml.rb +31 -0
- data/lib/lutaml/model/xml_adapter/element.rb +11 -25
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +6 -223
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +13 -163
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +10 -207
- data/lib/lutaml/model/yaml/document.rb +10 -0
- data/lib/lutaml/model/yaml/mapping.rb +19 -0
- data/lib/lutaml/model/yaml/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{yaml_adapter/standard_yaml_adapter.rb → yaml/standard_adapter.rb} +4 -3
- data/lib/lutaml/model/yaml/transform.rb +8 -0
- data/lib/lutaml/model/yaml.rb +21 -0
- data/lib/lutaml/model.rb +40 -4
- data/lutaml-model.gemspec +0 -4
- data/spec/benchmarks/xml_parsing_benchmark_spec.rb +7 -7
- data/spec/fixtures/person.rb +5 -5
- data/spec/lutaml/model/attribute_spec.rb +37 -1
- data/spec/lutaml/model/cdata_spec.rb +9 -9
- data/spec/lutaml/model/collection_spec.rb +50 -2
- data/spec/lutaml/model/comparable_model_spec.rb +92 -27
- data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +598 -0
- data/spec/lutaml/model/custom_vobject_adapter_spec.rb +1226 -0
- data/spec/lutaml/model/defaults_spec.rb +1 -1
- data/spec/lutaml/model/enum_spec.rb +1 -1
- data/spec/lutaml/model/group_spec.rb +333 -20
- data/spec/lutaml/model/hash/adapter_spec.rb +255 -0
- data/spec/lutaml/model/json_adapter_spec.rb +6 -6
- data/spec/lutaml/model/key_value_mapping_spec.rb +65 -3
- data/spec/lutaml/model/mixed_content_spec.rb +24 -24
- data/spec/lutaml/model/multiple_mapping_spec.rb +5 -5
- data/spec/lutaml/model/ordered_content_spec.rb +6 -6
- data/spec/lutaml/model/polymorphic_spec.rb +526 -0
- data/spec/lutaml/model/render_empty_spec.rb +194 -0
- data/spec/lutaml/model/render_nil_spec.rb +206 -22
- data/spec/lutaml/model/root_mappings_spec.rb +3 -3
- data/spec/lutaml/model/schema/xml_compiler_spec.rb +6 -6
- data/spec/lutaml/model/serializable_spec.rb +179 -103
- data/spec/lutaml/model/simple_model_spec.rb +9 -9
- data/spec/lutaml/model/toml_adapter_spec.rb +6 -6
- data/spec/lutaml/model/toml_spec.rb +51 -0
- data/spec/lutaml/model/transformation_spec.rb +72 -15
- data/spec/lutaml/model/uninitialized_class_spec.rb +96 -0
- data/spec/lutaml/model/value_map_spec.rb +240 -0
- data/spec/lutaml/model/xml/namespace/nested_with_explicit_namespace_spec.rb +85 -0
- data/spec/lutaml/model/xml/namespace_spec.rb +57 -0
- data/spec/lutaml/model/xml/xml_element_spec.rb +93 -0
- data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +6 -6
- data/spec/lutaml/model/xml_adapter_spec.rb +6 -6
- data/spec/lutaml/model/xml_mapping_rule_spec.rb +105 -5
- data/spec/lutaml/model/xml_mapping_spec.rb +70 -16
- data/spec/lutaml/model/xml_spec.rb +63 -0
- data/spec/lutaml/model/yaml_adapter_spec.rb +3 -5
- data/spec/sample_model_spec.rb +3 -3
- data/spec/spec_helper.rb +3 -3
- metadata +76 -59
- data/lib/lutaml/model/json_adapter/json_document.rb +0 -20
- data/lib/lutaml/model/json_adapter/json_object.rb +0 -28
- data/lib/lutaml/model/loggable.rb +0 -15
- data/lib/lutaml/model/mapping_rule.rb +0 -109
- data/lib/lutaml/model/toml_adapter/toml_document.rb +0 -20
- data/lib/lutaml/model/toml_adapter/toml_object.rb +0 -28
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +0 -20
- data/lib/lutaml/model/toml_adapter.rb +0 -6
- data/lib/lutaml/model/xml_mapping.rb +0 -307
- data/lib/lutaml/model/xml_mapping_rule.rb +0 -122
- data/lib/lutaml/model/yaml_adapter/yaml_document.rb +0 -20
- data/lib/lutaml/model/yaml_adapter/yaml_object.rb +0 -28
- data/lib/lutaml/model/yaml_adapter.rb +0 -8
@@ -21,35 +21,80 @@ class RenderNil < Lutaml::Model::Serializable
|
|
21
21
|
attribute :render_nil_nested, RenderNilNested
|
22
22
|
|
23
23
|
json do
|
24
|
-
map "name", to: :name, render_nil: true
|
25
|
-
map "clay_type", to: :clay_type, render_nil: true
|
26
|
-
map "glaze", to: :glaze, render_nil: true
|
27
|
-
map "dimensions", to: :dimensions,
|
24
|
+
map "name", to: :name, render_nil: true, render_empty: true
|
25
|
+
map "clay_type", to: :clay_type, render_nil: true, render_empty: true
|
26
|
+
map "glaze", to: :glaze, render_nil: true, render_empty: true
|
27
|
+
map "dimensions", to: :dimensions, render_empty: false
|
28
28
|
end
|
29
29
|
|
30
30
|
xml do
|
31
31
|
root "render_nil"
|
32
|
-
map_element "name", to: :name, render_nil: true
|
33
|
-
map_element "clay_type", to: :clay_type, render_nil: false
|
34
|
-
map_element "glaze", to: :glaze, render_nil: true
|
32
|
+
map_element "name", to: :name, render_nil: true, render_empty: true
|
33
|
+
map_element "clay_type", to: :clay_type, render_nil: false, render_empty: true
|
34
|
+
map_element "glaze", to: :glaze, render_nil: true, render_empty: true
|
35
35
|
map_element "render_nil_nested", to: :render_nil_nested, render_nil: true,
|
36
36
|
render_default: true
|
37
|
-
map_element "dimensions", to: :dimensions,
|
37
|
+
map_element "dimensions", to: :dimensions, render_empty: false
|
38
38
|
end
|
39
39
|
|
40
40
|
yaml do
|
41
|
-
map "name", to: :name, render_nil: true
|
42
|
-
map "clay_type", to: :clay_type, render_nil: false
|
43
|
-
map "glaze", to: :glaze, render_nil: true
|
44
|
-
map "dimensions", to: :dimensions,
|
41
|
+
map "name", to: :name, render_nil: true, render_empty: true
|
42
|
+
map "clay_type", to: :clay_type, render_nil: false, render_empty: true
|
43
|
+
map "glaze", to: :glaze, render_nil: true, render_empty: true
|
44
|
+
map "dimensions", to: :dimensions, render_empty: false
|
45
45
|
map "render_nil_nested", to: :render_nil_nested, render_nil: false
|
46
46
|
end
|
47
47
|
|
48
48
|
toml do
|
49
|
-
map "name", to: :name, render_nil: true
|
50
|
-
map "clay_type", to: :clay_type, render_nil: false
|
51
|
-
map "glaze", to: :glaze, render_nil: true
|
52
|
-
map "dimensions", to: :dimensions,
|
49
|
+
map "name", to: :name, render_nil: :empty, render_empty: true
|
50
|
+
map "clay_type", to: :clay_type, render_nil: false, render_empty: true
|
51
|
+
map "glaze", to: :glaze, render_nil: false, render_empty: true
|
52
|
+
map "dimensions", to: :dimensions, render_empty: false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module RenderNilSpec
|
57
|
+
class OmitNilModel < Lutaml::Model::Serializable
|
58
|
+
attribute :items, :string, collection: true
|
59
|
+
|
60
|
+
xml do
|
61
|
+
root "omit-nil-model"
|
62
|
+
map_element "items", to: :items, render_nil: :omit
|
63
|
+
end
|
64
|
+
|
65
|
+
key_value do
|
66
|
+
map "items", to: :items, render_nil: :omit
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class ExplicitNilModel < Lutaml::Model::Serializable
|
71
|
+
attribute :items, :string, collection: true
|
72
|
+
|
73
|
+
xml do
|
74
|
+
root "explicit-nil-model"
|
75
|
+
map_element "items", to: :items, render_nil: :as_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
yaml do
|
79
|
+
map "items", to: :items, render_nil: :as_nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class AsBlankNilModel < Lutaml::Model::Serializable
|
84
|
+
attribute :items, :string, collection: true
|
85
|
+
|
86
|
+
xml do
|
87
|
+
root "omit-nil-model"
|
88
|
+
map_element "items", to: :items, render_nil: :as_blank
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class AsEmptyNilModel < Lutaml::Model::Serializable
|
93
|
+
attribute :items, :string, collection: true
|
94
|
+
|
95
|
+
yaml do
|
96
|
+
map "items", to: :items, render_nil: :as_empty
|
97
|
+
end
|
53
98
|
end
|
54
99
|
end
|
55
100
|
|
@@ -82,14 +127,14 @@ RSpec.describe RenderNil do
|
|
82
127
|
expect(pottery.name).to be_nil
|
83
128
|
expect(pottery.clay_type).to be_nil
|
84
129
|
expect(pottery.glaze).to be_nil
|
85
|
-
expect(pottery.dimensions).to
|
130
|
+
expect(pottery.dimensions).to be_nil
|
86
131
|
end
|
87
132
|
|
88
133
|
it "serializes to XML with render_nil option" do
|
89
134
|
expected_xml = <<~XML
|
90
135
|
<render_nil>
|
91
|
-
<name/>
|
92
|
-
<glaze/>
|
136
|
+
<name xsi:nil="true"/>
|
137
|
+
<glaze xsi:nil="true"/>
|
93
138
|
<render_nil_nested/>
|
94
139
|
</render_nil>
|
95
140
|
XML
|
@@ -100,8 +145,8 @@ RSpec.describe RenderNil do
|
|
100
145
|
it "deserializes from XML with render_nil option" do
|
101
146
|
xml = <<~XML
|
102
147
|
<render_nil>
|
103
|
-
<name/>
|
104
|
-
<glaze/>
|
148
|
+
<name xsi:nil="true" />
|
149
|
+
<glaze xsi:nil="true" />
|
105
150
|
</render_nil>
|
106
151
|
XML
|
107
152
|
|
@@ -148,7 +193,7 @@ RSpec.describe RenderNil do
|
|
148
193
|
}
|
149
194
|
end
|
150
195
|
|
151
|
-
it "does not
|
196
|
+
it "does not treat empty string as nil" do
|
152
197
|
expected_yaml = <<~YAML
|
153
198
|
---
|
154
199
|
name: ''
|
@@ -165,4 +210,143 @@ RSpec.describe RenderNil do
|
|
165
210
|
expect(generated_yaml).to eq(expected_yaml.strip)
|
166
211
|
end
|
167
212
|
end
|
213
|
+
|
214
|
+
describe "render_nil option" do
|
215
|
+
context "when :omit" do
|
216
|
+
let(:model) { RenderNilSpec::OmitNilModel.new(items: nil) }
|
217
|
+
|
218
|
+
describe "YAML" do
|
219
|
+
let(:parsed) do
|
220
|
+
RenderNilSpec::OmitNilModel.from_yaml(yaml)
|
221
|
+
end
|
222
|
+
|
223
|
+
let(:yaml) do
|
224
|
+
<<~YAML
|
225
|
+
---
|
226
|
+
items:
|
227
|
+
YAML
|
228
|
+
end
|
229
|
+
|
230
|
+
it "omits nil collections while deserialize" do
|
231
|
+
expect(model.items).to be_nil
|
232
|
+
end
|
233
|
+
|
234
|
+
it "omits nil collections" do
|
235
|
+
expect(parsed.to_yaml.strip).to eq("--- {}")
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "XML" do
|
240
|
+
let(:parsed) { RenderNilSpec::OmitNilModel.from_xml(xml) }
|
241
|
+
|
242
|
+
let(:xml) do
|
243
|
+
<<~XML
|
244
|
+
<omit-nil-model/>
|
245
|
+
XML
|
246
|
+
end
|
247
|
+
|
248
|
+
it "omits nil collection" do
|
249
|
+
expect(model.to_xml).not_to include("<items")
|
250
|
+
end
|
251
|
+
|
252
|
+
it "omits nil collections while deserialize" do
|
253
|
+
expect(parsed.items).to be_nil
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context "when :as_nil" do
|
259
|
+
let(:model) { RenderNilSpec::ExplicitNilModel.new(items: nil) }
|
260
|
+
|
261
|
+
describe "YAML" do
|
262
|
+
let(:yaml) do
|
263
|
+
<<~YAML
|
264
|
+
---
|
265
|
+
items:
|
266
|
+
YAML
|
267
|
+
end
|
268
|
+
|
269
|
+
let(:parsed) do
|
270
|
+
RenderNilSpec::ExplicitNilModel.from_yaml(yaml)
|
271
|
+
end
|
272
|
+
|
273
|
+
it "renders explicit nil" do
|
274
|
+
expect(model.to_yaml).to include("items:")
|
275
|
+
end
|
276
|
+
|
277
|
+
it "sets nil values while deserialize" do
|
278
|
+
expect(parsed.items).to be_nil
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "XML" do
|
283
|
+
let(:xml) do
|
284
|
+
<<~XML
|
285
|
+
<explicit-nil-model>
|
286
|
+
<items xsi:nil="true"/>
|
287
|
+
</explicit-nil-model>
|
288
|
+
XML
|
289
|
+
end
|
290
|
+
|
291
|
+
let(:parsed) do
|
292
|
+
RenderNilSpec::ExplicitNilModel.from_xml(xml)
|
293
|
+
end
|
294
|
+
|
295
|
+
it "renders explicit nil" do
|
296
|
+
expect(model.to_xml).to include('<items xsi:nil="true"/>')
|
297
|
+
end
|
298
|
+
|
299
|
+
it "sets nil values while deserialize" do
|
300
|
+
expect(parsed.items).to be_nil
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
context "when :as_blank" do
|
306
|
+
let(:model) { RenderNilSpec::AsBlankNilModel.new(items: nil) }
|
307
|
+
|
308
|
+
let(:parsed) do
|
309
|
+
RenderNilSpec::AsBlankNilModel.from_xml(xml)
|
310
|
+
end
|
311
|
+
|
312
|
+
let(:xml) do
|
313
|
+
<<~XML
|
314
|
+
<explicit-nil-model>
|
315
|
+
<items/>
|
316
|
+
</explicit-nil-model>
|
317
|
+
XML
|
318
|
+
end
|
319
|
+
|
320
|
+
it "creates blank element from nil collections" do
|
321
|
+
expect(model.to_xml).to include("<items/>")
|
322
|
+
end
|
323
|
+
|
324
|
+
it "sets blank values while deserialize" do
|
325
|
+
expect(parsed.items).to eq([])
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
context "when :as_empty" do
|
330
|
+
let(:model) { RenderNilSpec::AsEmptyNilModel.new(items: nil) }
|
331
|
+
|
332
|
+
let(:parsed) do
|
333
|
+
RenderNilSpec::AsEmptyNilModel.from_yaml(yaml)
|
334
|
+
end
|
335
|
+
|
336
|
+
let(:yaml) do
|
337
|
+
<<~YAML
|
338
|
+
---
|
339
|
+
items:
|
340
|
+
YAML
|
341
|
+
end
|
342
|
+
|
343
|
+
it "creates key and empty collection" do
|
344
|
+
expect(model.to_yaml).to include("items: []")
|
345
|
+
end
|
346
|
+
|
347
|
+
it "sets nil value while deserialize" do
|
348
|
+
expect(parsed.items).to be_nil
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
168
352
|
end
|
@@ -283,15 +283,15 @@ RSpec.describe "RootMapping" do
|
|
283
283
|
end
|
284
284
|
end
|
285
285
|
|
286
|
-
describe Lutaml::Model::
|
286
|
+
describe Lutaml::Model::Yaml::StandardAdapter do
|
287
287
|
it_behaves_like "having root mappings", :yaml
|
288
288
|
end
|
289
289
|
|
290
|
-
describe Lutaml::Model::
|
290
|
+
describe Lutaml::Model::Json::StandardAdapter do
|
291
291
|
it_behaves_like "having root mappings", :json
|
292
292
|
end
|
293
293
|
|
294
|
-
describe Lutaml::Model::
|
294
|
+
describe Lutaml::Model::Toml::TomlRbAdapter do
|
295
295
|
it_behaves_like "having root mappings", :toml
|
296
296
|
end
|
297
297
|
end
|
@@ -471,7 +471,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
471
471
|
Lutaml::Xsd::SimpleContent.new.tap do |ct|
|
472
472
|
ct.extension = Lutaml::Xsd::ExtensionSimpleContent.new(base: "test_extension")
|
473
473
|
ct.element_order = [
|
474
|
-
Lutaml::Model::
|
474
|
+
Lutaml::Model::Xml::Element.new("Element", "extension"),
|
475
475
|
]
|
476
476
|
end
|
477
477
|
end
|
@@ -488,7 +488,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
488
488
|
Lutaml::Xsd::SimpleContent.new.tap do |ct|
|
489
489
|
ct.restriction = Lutaml::Xsd::RestrictionSimpleContent.new(base: "test_restriction")
|
490
490
|
ct.element_order = [
|
491
|
-
Lutaml::Model::
|
491
|
+
Lutaml::Model::Xml::Element.new("Element", "restriction"),
|
492
492
|
]
|
493
493
|
end
|
494
494
|
end
|
@@ -870,7 +870,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
870
870
|
element.min_occurs = 0
|
871
871
|
element.max_occurs = 1
|
872
872
|
element.complex_type = Lutaml::Xsd::ComplexType.new(name: "test_complex_type")
|
873
|
-
element.element_order = [Lutaml::Model::
|
873
|
+
element.element_order = [Lutaml::Model::Xml::Element.new("Element", "complex_type")]
|
874
874
|
end
|
875
875
|
end
|
876
876
|
|
@@ -910,7 +910,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
910
910
|
element.type = "test_type"
|
911
911
|
element.name = "test_name"
|
912
912
|
element.complex_type = Lutaml::Xsd::ComplexType.new(name: "test_complex_type")
|
913
|
-
element.element_order = [Lutaml::Model::
|
913
|
+
element.element_order = [Lutaml::Model::Xml::Element.new("Element", "complex_type")]
|
914
914
|
end
|
915
915
|
end
|
916
916
|
|
@@ -1143,7 +1143,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
1143
1143
|
end
|
1144
1144
|
|
1145
1145
|
it "raises an error when element_order contains elements that isn't an attribute of the instance" do
|
1146
|
-
element.element_order << Lutaml::Model::
|
1146
|
+
element.element_order << Lutaml::Model::Xml::Element.new("Element", "test_element")
|
1147
1147
|
expect { resolved_element_order }.to raise_error(NoMethodError)
|
1148
1148
|
end
|
1149
1149
|
|
@@ -1915,7 +1915,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
1915
1915
|
end
|
1916
1916
|
|
1917
1917
|
def create_pattern_mapping(array)
|
1918
|
-
array.map { |type, text| Lutaml::Model::
|
1918
|
+
array.map { |type, text| Lutaml::Model::Xml::Element.new(type, text) }
|
1919
1919
|
end
|
1920
1920
|
|
1921
1921
|
def to_mapping_hash(content)
|
@@ -96,6 +96,48 @@ module SerializeableSpec
|
|
96
96
|
}
|
97
97
|
end
|
98
98
|
end
|
99
|
+
|
100
|
+
### Single option serialization
|
101
|
+
|
102
|
+
class SingleOptionModel < Lutaml::Model::Serializable
|
103
|
+
attribute :name, :string
|
104
|
+
attribute :age, :integer
|
105
|
+
attribute :phone, :string
|
106
|
+
attribute :address, :string
|
107
|
+
|
108
|
+
json do
|
109
|
+
map "name", to: :name
|
110
|
+
map "age", to: :age
|
111
|
+
map "phone", to: :phone, with: { to: :phone_to_json }
|
112
|
+
map "address", to: :address, with: { from: :address_from_json }
|
113
|
+
end
|
114
|
+
|
115
|
+
xml do
|
116
|
+
root "person"
|
117
|
+
map_element "name", to: :name
|
118
|
+
map_element "age", to: :age
|
119
|
+
map_element "phone", to: :phone, with: { to: :phone_to_xml }
|
120
|
+
map_element "address", to: :address, with: { from: :address_from_xml }
|
121
|
+
end
|
122
|
+
|
123
|
+
def phone_to_json(model, doc)
|
124
|
+
doc["phone"] = "+1-#{model.phone}"
|
125
|
+
end
|
126
|
+
|
127
|
+
def address_from_json(model, value)
|
128
|
+
model.address = value.sub(/^Address: /, "")
|
129
|
+
end
|
130
|
+
|
131
|
+
def phone_to_xml(model, parent, doc)
|
132
|
+
el = doc.create_element("phone")
|
133
|
+
doc.add_text(el, "+1-#{model.phone}")
|
134
|
+
doc.add_element(parent, el)
|
135
|
+
end
|
136
|
+
|
137
|
+
def address_from_xml(model, value)
|
138
|
+
model.address = value.text.sub(/^Address: /, "")
|
139
|
+
end
|
140
|
+
end
|
99
141
|
end
|
100
142
|
|
101
143
|
RSpec.describe Lutaml::Model::Serializable do
|
@@ -151,48 +193,6 @@ RSpec.describe Lutaml::Model::Serializable do
|
|
151
193
|
end
|
152
194
|
end
|
153
195
|
|
154
|
-
describe ".hash_representation" do
|
155
|
-
context "when model is separate" do
|
156
|
-
let(:instance) do
|
157
|
-
SerializeableSpec::TestModel.new(name: "John", age: 18)
|
158
|
-
end
|
159
|
-
|
160
|
-
let(:expected_hash) do
|
161
|
-
{
|
162
|
-
"name" => "John",
|
163
|
-
"age" => "18",
|
164
|
-
}
|
165
|
-
end
|
166
|
-
|
167
|
-
it "return hash representation" do
|
168
|
-
generate_hash = SerializeableSpec::TestModelMapper.hash_representation(
|
169
|
-
instance, :yaml
|
170
|
-
)
|
171
|
-
expect(generate_hash).to eq(expected_hash)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
context "when model is self" do
|
176
|
-
let(:instance) do
|
177
|
-
SerializeableSpec::TestMapper.new(name: "John", age: 18)
|
178
|
-
end
|
179
|
-
|
180
|
-
let(:expected_hash) do
|
181
|
-
{
|
182
|
-
"na" => "John",
|
183
|
-
"ag" => "18",
|
184
|
-
}
|
185
|
-
end
|
186
|
-
|
187
|
-
it "return hash representation" do
|
188
|
-
generate_hash = SerializeableSpec::TestMapper.hash_representation(
|
189
|
-
instance, :yaml
|
190
|
-
)
|
191
|
-
expect(generate_hash).to eq(expected_hash)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
196
|
describe ".mappings_for" do
|
197
197
|
context "when mapping is defined" do
|
198
198
|
it "returns the defined mapping" do
|
@@ -221,67 +221,68 @@ RSpec.describe Lutaml::Model::Serializable do
|
|
221
221
|
end
|
222
222
|
end
|
223
223
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
end
|
224
|
+
# TODO: Move to key_value_transform specs
|
225
|
+
# describe ".translate_mappings" do
|
226
|
+
# let(:child_mappings) do
|
227
|
+
# {
|
228
|
+
# id: :key,
|
229
|
+
# path: %i[path link],
|
230
|
+
# name: %i[path name],
|
231
|
+
# }
|
232
|
+
# end
|
233
|
+
|
234
|
+
# let(:hash) do
|
235
|
+
# {
|
236
|
+
# "foo" => {
|
237
|
+
# "path" => {
|
238
|
+
# "link" => "link one",
|
239
|
+
# "name" => "one",
|
240
|
+
# },
|
241
|
+
# },
|
242
|
+
# "abc" => {
|
243
|
+
# "path" => {
|
244
|
+
# "link" => "link two",
|
245
|
+
# "name" => "two",
|
246
|
+
# },
|
247
|
+
# },
|
248
|
+
# "hello" => {
|
249
|
+
# "path" => {
|
250
|
+
# "link" => "link three",
|
251
|
+
# "name" => "three",
|
252
|
+
# },
|
253
|
+
# },
|
254
|
+
# }
|
255
|
+
# end
|
256
|
+
|
257
|
+
# let(:attr) { SerializeableSpec::TranslateMappings.attributes[:translate] }
|
258
|
+
|
259
|
+
# let(:expected_value) do
|
260
|
+
# [
|
261
|
+
# SerializeableSpec::TranslateHelper.new({
|
262
|
+
# "id" => "foo",
|
263
|
+
# "name" => "one",
|
264
|
+
# "path" => "link one",
|
265
|
+
# }),
|
266
|
+
# SerializeableSpec::TranslateHelper.new({
|
267
|
+
# "id" => "abc",
|
268
|
+
# "name" => "two",
|
269
|
+
# "path" => "link two",
|
270
|
+
# }),
|
271
|
+
# SerializeableSpec::TranslateHelper.new({
|
272
|
+
# "id" => "hello",
|
273
|
+
# "name" => "three",
|
274
|
+
# "path" => "link three",
|
275
|
+
# }),
|
276
|
+
# ]
|
277
|
+
# end
|
278
|
+
|
279
|
+
# it "generates hash based on child_mappings" do
|
280
|
+
# actual_value = described_class.translate_mappings(hash, child_mappings, attr, :yaml)
|
281
|
+
|
282
|
+
# expect(actual_value.map { |obj| [obj.id, obj.name, obj.path] })
|
283
|
+
# .to eq(expected_value.map { |obj| [obj.id, obj.name, obj.path] })
|
284
|
+
# end
|
285
|
+
# end
|
285
286
|
|
286
287
|
describe "#key_value" do
|
287
288
|
let(:model) { SerializeableSpec::KeyValueMapper }
|
@@ -386,4 +387,79 @@ RSpec.describe Lutaml::Model::Serializable do
|
|
386
387
|
end
|
387
388
|
end
|
388
389
|
end
|
390
|
+
|
391
|
+
describe "Single option serialization" do
|
392
|
+
let(:attributes) do
|
393
|
+
{
|
394
|
+
name: "John Doe",
|
395
|
+
age: 30,
|
396
|
+
phone: "123-456-7890",
|
397
|
+
address: "123 Main St",
|
398
|
+
}
|
399
|
+
end
|
400
|
+
|
401
|
+
let(:model) { SerializeableSpec::SingleOptionModel.new(attributes) }
|
402
|
+
|
403
|
+
describe "JSON serialization" do
|
404
|
+
let(:expected_json) do
|
405
|
+
{
|
406
|
+
name: "John Doe",
|
407
|
+
age: 30,
|
408
|
+
phone: "+1-123-456-7890",
|
409
|
+
address: "123 Main St",
|
410
|
+
}.to_json
|
411
|
+
end
|
412
|
+
|
413
|
+
let(:parsed) do
|
414
|
+
SerializeableSpec::SingleOptionModel.from_json(
|
415
|
+
{
|
416
|
+
name: "John Doe",
|
417
|
+
age: 30,
|
418
|
+
phone: "123-456-7890",
|
419
|
+
address: "Address: 123 Main St",
|
420
|
+
}.to_json,
|
421
|
+
)
|
422
|
+
end
|
423
|
+
|
424
|
+
it "serializes to JSON with custom name transformation" do
|
425
|
+
expect(model.to_json).to eq(expected_json)
|
426
|
+
end
|
427
|
+
|
428
|
+
it "deserializes from JSON with custom name transformation" do
|
429
|
+
expect(parsed).to eq(model)
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
describe "XML serialization" do
|
434
|
+
let(:expected_xml) do
|
435
|
+
<<~XML
|
436
|
+
<person>
|
437
|
+
<name>John Doe</name>
|
438
|
+
<age>30</age>
|
439
|
+
<phone>+1-123-456-7890</phone>
|
440
|
+
<address>123 Main St</address>
|
441
|
+
</person>
|
442
|
+
XML
|
443
|
+
end
|
444
|
+
|
445
|
+
let(:parsed) do
|
446
|
+
SerializeableSpec::SingleOptionModel.from_xml <<~XML
|
447
|
+
<person>
|
448
|
+
<name>John Doe</name>
|
449
|
+
<age>30</age>
|
450
|
+
<phone>123-456-7890</phone>
|
451
|
+
<address>Address: 123 Main St</address>
|
452
|
+
</person>
|
453
|
+
XML
|
454
|
+
end
|
455
|
+
|
456
|
+
it "serializes to XML with custom name transformation" do
|
457
|
+
expect(model.to_xml).to be_equivalent_to(expected_xml)
|
458
|
+
end
|
459
|
+
|
460
|
+
it "deserializes from XML with custom name transformation" do
|
461
|
+
expect(parsed).to eq(model)
|
462
|
+
end
|
463
|
+
end
|
464
|
+
end
|
389
465
|
end
|