shale 0.3.1 → 0.6.0
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/CHANGELOG.md +37 -0
- data/README.md +398 -41
- data/exe/shaleb +108 -36
- data/lib/shale/adapter/nokogiri/document.rb +97 -0
- data/lib/shale/adapter/nokogiri/node.rb +100 -0
- data/lib/shale/adapter/nokogiri.rb +11 -151
- data/lib/shale/adapter/ox/document.rb +90 -0
- data/lib/shale/adapter/ox/node.rb +97 -0
- data/lib/shale/adapter/ox.rb +9 -134
- data/lib/shale/adapter/rexml/document.rb +98 -0
- data/lib/shale/adapter/rexml/node.rb +99 -0
- data/lib/shale/adapter/rexml.rb +9 -150
- data/lib/shale/adapter/toml_rb.rb +34 -0
- data/lib/shale/attribute.rb +6 -0
- data/lib/shale/error.rb +56 -0
- data/lib/shale/mapper.rb +67 -13
- data/lib/shale/mapping/descriptor/xml.rb +10 -1
- data/lib/shale/mapping/dict.rb +18 -0
- data/lib/shale/mapping/xml.rb +40 -5
- data/lib/shale/schema/compiler/boolean.rb +21 -0
- data/lib/shale/schema/compiler/complex.rb +88 -0
- data/lib/shale/schema/compiler/date.rb +21 -0
- data/lib/shale/schema/compiler/float.rb +21 -0
- data/lib/shale/schema/compiler/integer.rb +21 -0
- data/lib/shale/schema/compiler/property.rb +70 -0
- data/lib/shale/schema/compiler/string.rb +21 -0
- data/lib/shale/schema/compiler/time.rb +21 -0
- data/lib/shale/schema/compiler/value.rb +21 -0
- data/lib/shale/schema/compiler/xml_complex.rb +50 -0
- data/lib/shale/schema/compiler/xml_property.rb +73 -0
- data/lib/shale/schema/json_compiler.rb +331 -0
- data/lib/shale/schema/{json → json_generator}/base.rb +2 -2
- data/lib/shale/schema/{json → json_generator}/boolean.rb +1 -1
- data/lib/shale/schema/{json → json_generator}/collection.rb +2 -2
- data/lib/shale/schema/{json → json_generator}/date.rb +1 -1
- data/lib/shale/schema/{json → json_generator}/float.rb +1 -1
- data/lib/shale/schema/{json → json_generator}/integer.rb +1 -1
- data/lib/shale/schema/{json → json_generator}/object.rb +5 -2
- data/lib/shale/schema/{json → json_generator}/ref.rb +1 -1
- data/lib/shale/schema/{json → json_generator}/schema.rb +6 -4
- data/lib/shale/schema/{json → json_generator}/string.rb +1 -1
- data/lib/shale/schema/{json → json_generator}/time.rb +1 -1
- data/lib/shale/schema/json_generator/value.rb +23 -0
- data/lib/shale/schema/{json.rb → json_generator.rb} +36 -36
- data/lib/shale/schema/xml_compiler.rb +919 -0
- data/lib/shale/schema/{xml → xml_generator}/attribute.rb +1 -1
- data/lib/shale/schema/{xml → xml_generator}/complex_type.rb +5 -2
- data/lib/shale/schema/{xml → xml_generator}/element.rb +1 -1
- data/lib/shale/schema/{xml → xml_generator}/import.rb +1 -1
- data/lib/shale/schema/{xml → xml_generator}/ref_attribute.rb +1 -1
- data/lib/shale/schema/{xml → xml_generator}/ref_element.rb +1 -1
- data/lib/shale/schema/{xml → xml_generator}/schema.rb +5 -5
- data/lib/shale/schema/{xml → xml_generator}/typed_attribute.rb +1 -1
- data/lib/shale/schema/{xml → xml_generator}/typed_element.rb +1 -1
- data/lib/shale/schema/{xml.rb → xml_generator.rb} +25 -26
- data/lib/shale/schema.rb +44 -5
- data/lib/shale/type/{composite.rb → complex.rb} +156 -51
- data/lib/shale/type/value.rb +31 -2
- data/lib/shale/utils.rb +42 -7
- data/lib/shale/version.rb +1 -1
- data/lib/shale.rb +22 -19
- data/shale.gemspec +3 -3
- metadata +50 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 243b99a073ac189f66ae0fbfedd94a5715399de731d0e0fd1d970dad749d27a0
|
4
|
+
data.tar.gz: d2f57de2427574d710d6a6fe9ba35868fd162214ce8aa2092ddfb3fe1f5e7c3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9de1be5eccbb647f05b6573d783491f858fb56614f09c7c625e7fa922c7b89b5d38863a57defbe506d42f0b542b326e4ca61ecf308b94f7b35b4056751e0299e
|
7
|
+
data.tar.gz: a1e29fc097c130c55e45837af198e3cd4f7d3ad6a94b17d032eb31b8065f7ea013682836256d12127480965ed3733079e5badd7a8b0060e3bc60f00734fcc215
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,40 @@
|
|
1
|
+
## [0.6.0] - 2022-07-05
|
2
|
+
|
3
|
+
### Added
|
4
|
+
- Support for TOML
|
5
|
+
- Support for CDATA nodes in XML documents
|
6
|
+
- Support for using custom models
|
7
|
+
|
8
|
+
### Fixed
|
9
|
+
- Allow to map XML content using methods
|
10
|
+
- Prevent adding default mapping after mapping block was declared
|
11
|
+
|
12
|
+
## [0.5.0] - 2022-06-28
|
13
|
+
|
14
|
+
### Added
|
15
|
+
- Allow to generate Shale model from XML Schema
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
- Shale doesn't defaults to REXML anymore - XML adapter needs to be set explicitly
|
19
|
+
- Rename "JSONSchemaError" to "SchemaError"
|
20
|
+
- Rename "Composite" type to "Complex"
|
21
|
+
- Drop support for Ruby 2.6
|
22
|
+
|
23
|
+
## [0.4.0] - 2022-05-30
|
24
|
+
|
25
|
+
### Added
|
26
|
+
- Allow to add title to JSON Schema
|
27
|
+
- Map Shale::Type::Value to "anyType" XML Schema type
|
28
|
+
- Map Shale::Type::Value to "any" JSON Schema type
|
29
|
+
- Allow to generate Shale model from JSON Schema
|
30
|
+
|
31
|
+
### Changed
|
32
|
+
- Performance improvements
|
33
|
+
- Reformat README a little bit and fix typos
|
34
|
+
|
35
|
+
### Fixed
|
36
|
+
- Fix stack overflow caused by circular dependency when generating JSON and XML schemas
|
37
|
+
|
1
38
|
## [0.3.1] - 2022-04-29
|
2
39
|
|
3
40
|
### Changed
|
data/README.md
CHANGED
@@ -1,10 +1,23 @@
|
|
1
1
|
# Shale
|
2
2
|
|
3
|
-
Shale is a object mapper and serializer for JSON, YAML and XML.
|
3
|
+
Shale is a Ruby object mapper and serializer for JSON, YAML, TOML and XML.
|
4
|
+
It allows you to parse JSON, YAML, TOML and XML data and convert it into Ruby data structures,
|
5
|
+
as well as serialize data structures into JSON, YAML, TOML or XML.
|
6
|
+
|
7
|
+
Documentation with interactive examples is available at [Shale website](https://www.shalerb.org)
|
8
|
+
|
9
|
+
## Features
|
10
|
+
|
11
|
+
* Convert JSON, YAML, TOML and XML to Ruby data model
|
12
|
+
* Convert Ruby data model to JSON, YAML, TOML and XML
|
13
|
+
* Generate JSON and XML Schema from Ruby models
|
14
|
+
* Compile JSON and XML Schema into Ruby models
|
15
|
+
* Out of the box support for JSON, YAML, toml-rb, Nokogiri, REXML and Ox parsers
|
16
|
+
* Support for custom adapters
|
4
17
|
|
5
18
|
## Installation
|
6
19
|
|
7
|
-
Shale supports Ruby (MRI) 2.
|
20
|
+
Shale supports Ruby (MRI) 2.7+
|
8
21
|
|
9
22
|
Add this line to your application's Gemfile:
|
10
23
|
|
@@ -32,27 +45,31 @@ $ gem install shale
|
|
32
45
|
* [Converting object to JSON](#converting-object-to-json)
|
33
46
|
* [Converting YAML to object](#converting-yaml-to-object)
|
34
47
|
* [Converting object to YAML](#converting-object-to-yaml)
|
48
|
+
* [Converting TOML to object](#converting-toml-to-object)
|
49
|
+
* [Converting object to TOML](#converting-object-to-toml)
|
35
50
|
* [Converting Hash to object](#converting-hash-to-object)
|
36
51
|
* [Converting object to Hash](#converting-object-to-hash)
|
37
52
|
* [Converting XML to object](#converting-xml-to-object)
|
38
53
|
* [Converting object to XML](#converting-object-to-xml)
|
39
54
|
* [Mapping JSON keys to object attributes](#mapping-json-keys-to-object-attributes)
|
40
55
|
* [Mapping YAML keys to object attributes](#mapping-yaml-keys-to-object-attributes)
|
56
|
+
* [Mapping TOML keys to object attributes](#mapping-toml-keys-to-object-attributes)
|
41
57
|
* [Mapping Hash keys to object attributes](#mapping-hash-keys-to-object-attributes)
|
42
58
|
* [Mapping XML elements and attributes to object attributes](#mapping-xml-elements-and-attributes-to-object-attributes)
|
43
59
|
* [Using XML namespaces](#using-xml-namespaces)
|
44
60
|
* [Using methods to extract and generate data](#using-methods-to-extract-and-generate-data)
|
45
61
|
* [Pretty printing and XML declaration](#pretty-printing-and-xml-declaration)
|
62
|
+
* [Using custom models](#using-custom-models)
|
46
63
|
* [Supported types](#supported-types)
|
47
64
|
* [Writing your own type](#writing-your-own-type)
|
48
65
|
* [Adapters](#adapters)
|
49
66
|
* [Generating JSON Schema](#generating-json-schema)
|
67
|
+
* [Compiling JSON Schema into Shale model](#compiling-json-schema-into-shale-model)
|
50
68
|
* [Generating XML Schema](#generating-xml-schema)
|
69
|
+
* [Compiling XML Schema into Shale model](#compiling-xml-schema-into-shale-model)
|
51
70
|
|
52
71
|
## Usage
|
53
72
|
|
54
|
-
Documentation with interactive examples is available at [Shale website](https://www.shalerb.org)
|
55
|
-
|
56
73
|
### Simple use case
|
57
74
|
|
58
75
|
```ruby
|
@@ -126,6 +143,7 @@ DATA
|
|
126
143
|
|
127
144
|
```ruby
|
128
145
|
person.to_json
|
146
|
+
|
129
147
|
# =>
|
130
148
|
#
|
131
149
|
# {
|
@@ -164,6 +182,63 @@ DATA
|
|
164
182
|
|
165
183
|
```ruby
|
166
184
|
person.to_yaml
|
185
|
+
|
186
|
+
# =>
|
187
|
+
#
|
188
|
+
# ---
|
189
|
+
# first_name: John
|
190
|
+
# last_name: Doe
|
191
|
+
# age: 50
|
192
|
+
# married: false
|
193
|
+
# hobbies:
|
194
|
+
# - Singing
|
195
|
+
# - Dancing
|
196
|
+
# address:
|
197
|
+
# city: London
|
198
|
+
# street: Oxford Street
|
199
|
+
# zip: E1 6AN
|
200
|
+
```
|
201
|
+
|
202
|
+
### Converting TOML to object
|
203
|
+
|
204
|
+
To use TOML with Shale you have to set adapter you want to use.
|
205
|
+
Shale comes with adapter for [toml-rb](https://github.com/emancu/toml-rb).
|
206
|
+
For details see [Adapters](#adapters) section.
|
207
|
+
|
208
|
+
To set it, first make sure toml-rb gem is installed:
|
209
|
+
|
210
|
+
```
|
211
|
+
$ gem install shale
|
212
|
+
```
|
213
|
+
|
214
|
+
then setup adapter:
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
require 'shale/adapter/toml_rb'
|
218
|
+
Shale.toml_adapter = Shale::Adapter::TomlRB
|
219
|
+
```
|
220
|
+
|
221
|
+
Now you can use TOML with Shale:
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
person = Person.from_toml(<<~DATA)
|
225
|
+
first_name = "John"
|
226
|
+
last_name = "Doe"
|
227
|
+
age = 50
|
228
|
+
married = false
|
229
|
+
hobbies = ["Singing", "Dancing"]
|
230
|
+
[address]
|
231
|
+
city = "London"
|
232
|
+
street = "Oxford Street"
|
233
|
+
zip = "E1 6AN"
|
234
|
+
DATA
|
235
|
+
```
|
236
|
+
|
237
|
+
### Converting object to TOML
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
person.to_toml
|
241
|
+
|
167
242
|
# =>
|
168
243
|
#
|
169
244
|
# ---
|
@@ -201,6 +276,7 @@ person = Person.from_hash(
|
|
201
276
|
|
202
277
|
```ruby
|
203
278
|
person.to_hash
|
279
|
+
|
204
280
|
# =>
|
205
281
|
#
|
206
282
|
# {
|
@@ -215,6 +291,17 @@ person.to_hash
|
|
215
291
|
|
216
292
|
### Converting XML to object
|
217
293
|
|
294
|
+
To use XML with Shale you have to set adapter you want to use.
|
295
|
+
Shale comes with adapters for REXML, Nokogiri and OX parsers.
|
296
|
+
For details see [Adapters](#adapters) section.
|
297
|
+
|
298
|
+
```ruby
|
299
|
+
require 'shale/adapter/rexml'
|
300
|
+
Shale.xml_adapter = Shale::Adapter::REXML
|
301
|
+
```
|
302
|
+
|
303
|
+
Now you can use XML with Shale:
|
304
|
+
|
218
305
|
```ruby
|
219
306
|
person = Person.from_xml(<<~DATA)
|
220
307
|
<person>
|
@@ -237,6 +324,7 @@ DATA
|
|
237
324
|
|
238
325
|
```ruby
|
239
326
|
person.to_xml
|
327
|
+
|
240
328
|
# =>
|
241
329
|
#
|
242
330
|
# <person>
|
@@ -256,7 +344,9 @@ person.to_xml
|
|
256
344
|
|
257
345
|
### Mapping JSON keys to object attributes
|
258
346
|
|
259
|
-
By default keys are named the same as attributes. To use custom
|
347
|
+
By default keys are named the same as attributes. To use custom keys use:
|
348
|
+
|
349
|
+
:warning: **Declaring custom mapping removes default mapping for given format!**
|
260
350
|
|
261
351
|
```ruby
|
262
352
|
class Person < Shale::Mapper
|
@@ -284,6 +374,20 @@ class Person < Shale::Mapper
|
|
284
374
|
end
|
285
375
|
```
|
286
376
|
|
377
|
+
### Mapping TOML keys to object attributes
|
378
|
+
|
379
|
+
```ruby
|
380
|
+
class Person < Shale::Mapper
|
381
|
+
attribute :first_name, Shale::Type::String
|
382
|
+
attribute :last_name, Shale::Type::String
|
383
|
+
|
384
|
+
toml do
|
385
|
+
map 'firstName', to: :first_name
|
386
|
+
map 'lastName', to: :last_name
|
387
|
+
end
|
388
|
+
end
|
389
|
+
```
|
390
|
+
|
287
391
|
### Mapping Hash keys to object attributes
|
288
392
|
|
289
393
|
```ruby
|
@@ -300,7 +404,7 @@ end
|
|
300
404
|
|
301
405
|
### Mapping XML elements and attributes to object attributes
|
302
406
|
|
303
|
-
XML is more
|
407
|
+
XML is more complicated format than JSON or YAML. To map elements, attributes and content use:
|
304
408
|
|
305
409
|
```ruby
|
306
410
|
class Address < Shale::Mapper
|
@@ -354,9 +458,38 @@ DATA
|
|
354
458
|
- `map_attribute` - map element's attribute to attribute
|
355
459
|
- `map_content` - map first text node to attribute
|
356
460
|
|
357
|
-
|
461
|
+
You can use `cdata: true` option on `map_element` and `map_content` to handle CDATA nodes:
|
358
462
|
|
359
|
-
|
463
|
+
```ruby
|
464
|
+
class Address < Shale::Mapper
|
465
|
+
attribute :content, Shale::Type::String
|
466
|
+
|
467
|
+
xml do
|
468
|
+
map_content to: :content, cdata: true
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
class Person < Shale::Mapper
|
473
|
+
attribute :first_name, Shale::Type::String
|
474
|
+
attribute :address, Address
|
475
|
+
|
476
|
+
xml do
|
477
|
+
root 'Person'
|
478
|
+
|
479
|
+
map_element 'FirstName', to: :first_name, cdata: true
|
480
|
+
map_element 'Address', to: :address
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
person = Person.from_xml(<<~DATA)
|
485
|
+
<Person>
|
486
|
+
<FirstName><![CDATA[John]]></FirstName>
|
487
|
+
<Address><![CDATA[Oxford Street]]></Address>
|
488
|
+
</person>
|
489
|
+
DATA
|
490
|
+
```
|
491
|
+
|
492
|
+
### Using XML namespaces
|
360
493
|
|
361
494
|
To map namespaced elements and attributes use `namespace` and `prefix` properties on
|
362
495
|
`map_element` and `map_attribute`
|
@@ -385,7 +518,7 @@ DATA
|
|
385
518
|
```
|
386
519
|
|
387
520
|
To define default namespace for all elements use `namespace` declaration
|
388
|
-
(this will define namespace
|
521
|
+
(this will define namespace on elements only, if you want to define namespace on an attribute
|
389
522
|
explicitly declare it on `map_attribute`).
|
390
523
|
|
391
524
|
```ruby
|
@@ -445,42 +578,42 @@ class Person < Shale::Mapper
|
|
445
578
|
map_element 'Address', using: { from: :address_from_xml, to: :address_to_xml }
|
446
579
|
end
|
447
580
|
|
448
|
-
def hobbies_from_json(value)
|
449
|
-
|
581
|
+
def hobbies_from_json(model, value)
|
582
|
+
model.hobbies = value.split(',').map(&:strip)
|
450
583
|
end
|
451
584
|
|
452
|
-
def hobbies_to_json
|
453
|
-
hobbies.join(', ')
|
585
|
+
def hobbies_to_json(model)
|
586
|
+
model.hobbies.join(', ')
|
454
587
|
end
|
455
588
|
|
456
|
-
def address_from_json(value)
|
457
|
-
|
458
|
-
|
589
|
+
def address_from_json(model, value)
|
590
|
+
model.street = value['street']
|
591
|
+
model.city = value['city']
|
459
592
|
end
|
460
593
|
|
461
|
-
def address_to_json
|
462
|
-
{ 'street' => street, 'city' => city }
|
594
|
+
def address_to_json(model)
|
595
|
+
{ 'street' => model.street, 'city' => model.city }
|
463
596
|
end
|
464
597
|
|
465
|
-
def hobbies_from_xml(value)
|
466
|
-
|
598
|
+
def hobbies_from_xml(model, value)
|
599
|
+
model.hobbies = value.split(',').map(&:strip)
|
467
600
|
end
|
468
601
|
|
469
|
-
def hobbies_to_xml(element, doc)
|
470
|
-
doc.add_attribute(element, 'hobbies', hobbies.join(', '))
|
602
|
+
def hobbies_to_xml(model, element, doc)
|
603
|
+
doc.add_attribute(element, 'hobbies', model.hobbies.join(', '))
|
471
604
|
end
|
472
605
|
|
473
|
-
def address_from_xml(node)
|
474
|
-
|
475
|
-
|
606
|
+
def address_from_xml(model, node)
|
607
|
+
model.street = node.children.find { |e| e.name == 'Street' }.text
|
608
|
+
model.city = node.children.find { |e| e.name == 'City' }.text
|
476
609
|
end
|
477
610
|
|
478
|
-
def address_to_xml(parent, doc)
|
611
|
+
def address_to_xml(model, parent, doc)
|
479
612
|
street_element = doc.create_element('Street')
|
480
|
-
doc.add_text(street_element, street.to_s)
|
613
|
+
doc.add_text(street_element, model.street.to_s)
|
481
614
|
|
482
615
|
city_element = doc.create_element('City')
|
483
|
-
doc.add_text(city_element, city.to_s)
|
616
|
+
doc.add_text(city_element, model.city.to_s)
|
484
617
|
|
485
618
|
address_element = doc.create_element('Address')
|
486
619
|
doc.add_element(address_element, street_element)
|
@@ -505,7 +638,7 @@ person = Person.from_xml(<<~DATA)
|
|
505
638
|
<Street>Oxford Street</Street>
|
506
639
|
<City>London</City>
|
507
640
|
</Address>
|
508
|
-
</
|
641
|
+
</Person>
|
509
642
|
DATA
|
510
643
|
|
511
644
|
# =>
|
@@ -546,6 +679,67 @@ person.to_xml(:pretty, :declaration)
|
|
546
679
|
# </Person>
|
547
680
|
```
|
548
681
|
|
682
|
+
### Using custom models
|
683
|
+
|
684
|
+
By default Shale combines mapper and model into one class. If you want to use your own classes
|
685
|
+
as models you can do it by using `model` directive on the mapper:
|
686
|
+
|
687
|
+
```ruby
|
688
|
+
class Address
|
689
|
+
attr_accessor :street, :city
|
690
|
+
end
|
691
|
+
|
692
|
+
class Person
|
693
|
+
attr_accessor :first_name, :last_name, :address
|
694
|
+
end
|
695
|
+
|
696
|
+
class AddressMapper < Shale::Mapper
|
697
|
+
model Address
|
698
|
+
|
699
|
+
attribute :street, Shale::Type::String
|
700
|
+
attribute :city, Shale::Type::String
|
701
|
+
end
|
702
|
+
|
703
|
+
class PersonMapper < Shale::Mapper
|
704
|
+
model Person
|
705
|
+
|
706
|
+
attribute :first_name, Shale::Type::String
|
707
|
+
attribute :last_name, Shale::Type::String
|
708
|
+
attribute :address, AddressMapper
|
709
|
+
end
|
710
|
+
|
711
|
+
person = PersonMapper.from_json(<<~DATA)
|
712
|
+
{
|
713
|
+
"first_name": "John",
|
714
|
+
"last_name": "Doe",
|
715
|
+
"address": {
|
716
|
+
"street": "Oxford Street",
|
717
|
+
"city": "London"
|
718
|
+
}
|
719
|
+
}
|
720
|
+
DATA
|
721
|
+
|
722
|
+
# =>
|
723
|
+
#
|
724
|
+
# #<Person:0x0000000113d7a488
|
725
|
+
# @first_name="John",
|
726
|
+
# @last_name="Doe",
|
727
|
+
# @address=#<Address:0x0000000113d7a140 @street="Oxford Street", @city="London">>
|
728
|
+
|
729
|
+
PersonMapper.to_json(person, :pretty)
|
730
|
+
|
731
|
+
# =>
|
732
|
+
#
|
733
|
+
# {
|
734
|
+
# "first_name": "John",
|
735
|
+
# "last_name": "Doe",
|
736
|
+
# "address": {
|
737
|
+
# "street": "Oxford Street",
|
738
|
+
# "city": "London"
|
739
|
+
# }
|
740
|
+
# }
|
741
|
+
```
|
742
|
+
|
549
743
|
### Supported types
|
550
744
|
|
551
745
|
Shale supports these types out of the box:
|
@@ -574,10 +768,9 @@ end
|
|
574
768
|
### Adapters
|
575
769
|
|
576
770
|
Shale uses adapters for parsing and generating documents.
|
577
|
-
By default Ruby's standard JSON
|
578
|
-
REXML for XML.
|
771
|
+
By default Ruby's standard JSON, YAML parsers are used for handling JSON and YAML documents.
|
579
772
|
|
580
|
-
You can change it by providing your own adapter. For JSON and
|
773
|
+
You can change it by providing your own adapter. For JSON, YAML and TOML, adapter must implement
|
581
774
|
`.load` and `.dump` class methods.
|
582
775
|
|
583
776
|
```ruby
|
@@ -588,12 +781,25 @@ Shale.json_adapter = MultiJson
|
|
588
781
|
Shale.yaml_adapter = MyYamlAdapter
|
589
782
|
```
|
590
783
|
|
784
|
+
To handle TOML documents you have to set TOML adapter.
|
785
|
+
Shale provides adapter for `toml-rb` TOML parser:
|
786
|
+
|
787
|
+
```ruby
|
788
|
+
require 'shale'
|
789
|
+
|
790
|
+
require 'shale/adapter/toml_rb'
|
791
|
+
Shale.toml_adapter = Shale::Adapter::TomlRB
|
792
|
+
```
|
793
|
+
|
794
|
+
To handle XML documents you have to explicitly set XML adapter.
|
591
795
|
Shale provides adapters for most popular Ruby XML parsers:
|
592
796
|
|
797
|
+
:warning: **Ox doesn't support XML namespaces**
|
798
|
+
|
593
799
|
```ruby
|
594
800
|
require 'shale'
|
595
801
|
|
596
|
-
#
|
802
|
+
# if you want to use REXML:
|
597
803
|
|
598
804
|
require 'shale/adapter/rexml'
|
599
805
|
Shale.xml_adapter = Shale::Adapter::REXML
|
@@ -611,14 +817,19 @@ Shale.xml_adapter = Shale::Adapter::Ox
|
|
611
817
|
|
612
818
|
### Generating JSON Schema
|
613
819
|
|
614
|
-
|
820
|
+
:warning: Only **[Draft 2020-12](https://json-schema.org/draft/2020-12/schema)** JSON Schema is supported
|
615
821
|
|
616
|
-
|
822
|
+
To generate JSON Schema from your Shale data model use:
|
617
823
|
|
618
824
|
```ruby
|
619
825
|
require 'shale/schema'
|
620
826
|
|
621
|
-
Shale::Schema.to_json(
|
827
|
+
Shale::Schema.to_json(
|
828
|
+
Person,
|
829
|
+
id: 'http://foo.bar/schema/person',
|
830
|
+
description: 'My description',
|
831
|
+
pretty: true
|
832
|
+
)
|
622
833
|
|
623
834
|
# =>
|
624
835
|
#
|
@@ -663,7 +874,7 @@ Shale::Schema.to_json(Person, id: 'http://foo.bar/schema/person', description: '
|
|
663
874
|
You can also use a command line tool to do it:
|
664
875
|
|
665
876
|
```
|
666
|
-
$ shaleb -i data_model.rb -
|
877
|
+
$ shaleb -i data_model.rb -r Person -p
|
667
878
|
```
|
668
879
|
|
669
880
|
If you want to convert your own types to JSON Schema types use:
|
@@ -676,13 +887,83 @@ class MyEmailType < Shale::Type::Value
|
|
676
887
|
...
|
677
888
|
end
|
678
889
|
|
679
|
-
class MyEmailJSONType < Shale::Schema::
|
890
|
+
class MyEmailJSONType < Shale::Schema::JSONGenerator::Base
|
680
891
|
def as_type
|
681
892
|
{ 'type' => 'string', 'format' => 'email' }
|
682
893
|
end
|
683
894
|
end
|
684
895
|
|
685
|
-
Shale::Schema::
|
896
|
+
Shale::Schema::JSONGenerator.register_json_type(MyEmailType, MyEmailJSONType)
|
897
|
+
```
|
898
|
+
|
899
|
+
### Compiling JSON Schema into Shale model
|
900
|
+
|
901
|
+
:warning: Only **[Draft 2020-12](https://json-schema.org/draft/2020-12/schema)** JSON Schema is supported
|
902
|
+
|
903
|
+
To generate Shale data model from JSON Schema use:
|
904
|
+
|
905
|
+
```ruby
|
906
|
+
require 'shale/schema'
|
907
|
+
|
908
|
+
schema = <<~SCHEMA
|
909
|
+
{
|
910
|
+
"type": "object",
|
911
|
+
"properties": {
|
912
|
+
"firstName": { "type": "string" },
|
913
|
+
"lastName": { "type": "string" },
|
914
|
+
"address": {
|
915
|
+
"type": "object",
|
916
|
+
"properties": {
|
917
|
+
"street": { "type": "string" },
|
918
|
+
"city": { "type": "string" }
|
919
|
+
}
|
920
|
+
}
|
921
|
+
}
|
922
|
+
}
|
923
|
+
SCHEMA
|
924
|
+
|
925
|
+
Shale::Schema.from_json([schema], root_name: 'Person')
|
926
|
+
|
927
|
+
# =>
|
928
|
+
#
|
929
|
+
# {
|
930
|
+
# "address" => "
|
931
|
+
# require 'shale'
|
932
|
+
#
|
933
|
+
# class Address < Shale::Mapper
|
934
|
+
# attribute :street, Shale::Type::String
|
935
|
+
# attribute :city, Shale::Type::String
|
936
|
+
#
|
937
|
+
# json do
|
938
|
+
# map 'street', to: :street
|
939
|
+
# map 'city', to: :city
|
940
|
+
# end
|
941
|
+
# end
|
942
|
+
# ",
|
943
|
+
# "person" => "
|
944
|
+
# require 'shale'
|
945
|
+
#
|
946
|
+
# require_relative 'address'
|
947
|
+
#
|
948
|
+
# class Person < Shale::Mapper
|
949
|
+
# attribute :first_name, Shale::Type::String
|
950
|
+
# attribute :last_name, Shale::Type::String
|
951
|
+
# attribute :address, Address
|
952
|
+
#
|
953
|
+
# json do
|
954
|
+
# map 'firstName', to: :first_name
|
955
|
+
# map 'lastName', to: :last_name
|
956
|
+
# map 'address', to: :address
|
957
|
+
# end
|
958
|
+
# end
|
959
|
+
# "
|
960
|
+
# }
|
961
|
+
```
|
962
|
+
|
963
|
+
You can also use a command line tool to do it:
|
964
|
+
|
965
|
+
```
|
966
|
+
$ shaleb -c -i schema.json -r Person
|
686
967
|
```
|
687
968
|
|
688
969
|
### Generating XML Schema
|
@@ -735,7 +1016,7 @@ Shale::Schema.to_xml(Person, pretty: true)
|
|
735
1016
|
You can also use a command line tool to do it:
|
736
1017
|
|
737
1018
|
```
|
738
|
-
$ shaleb -i data_model.rb -
|
1019
|
+
$ shaleb -i data_model.rb -r Person -p -f xml
|
739
1020
|
```
|
740
1021
|
|
741
1022
|
If you want to convert your own types to XML Schema types use:
|
@@ -748,7 +1029,83 @@ class MyEmailType < Shale::Type::Value
|
|
748
1029
|
...
|
749
1030
|
end
|
750
1031
|
|
751
|
-
Shale::Schema::
|
1032
|
+
Shale::Schema::XMLGenerator.register_xml_type(MyEmailType, 'myEmailXMLType')
|
1033
|
+
```
|
1034
|
+
|
1035
|
+
### Compiling XML Schema into Shale model
|
1036
|
+
|
1037
|
+
To generate Shale data model from XML Schema use:
|
1038
|
+
|
1039
|
+
```ruby
|
1040
|
+
require 'shale/schema'
|
1041
|
+
|
1042
|
+
schema = <<~SCHEMA
|
1043
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
1044
|
+
<xs:element name="Person" type="Person" />
|
1045
|
+
|
1046
|
+
<xs:complexType name="Person">
|
1047
|
+
<xs:sequence>
|
1048
|
+
<xs:element name="FirstName" type="xs:string" />
|
1049
|
+
<xs:element name="LastName" type="xs:string" />
|
1050
|
+
<xs:element name="Address" type="Address" />
|
1051
|
+
</xs:sequence>
|
1052
|
+
</xs:complexType>
|
1053
|
+
|
1054
|
+
<xs:complexType name="Address">
|
1055
|
+
<xs:sequence>
|
1056
|
+
<xs:element name="Street" type="xs:string" />
|
1057
|
+
<xs:element name="City" type="xs:string" />
|
1058
|
+
</xs:sequence>
|
1059
|
+
</xs:complexType>
|
1060
|
+
</xs:schema>
|
1061
|
+
SCHEMA
|
1062
|
+
|
1063
|
+
Shale::Schema.from_xml([schema])
|
1064
|
+
|
1065
|
+
# =>
|
1066
|
+
#
|
1067
|
+
# {
|
1068
|
+
# "address" => "
|
1069
|
+
# require 'shale'
|
1070
|
+
#
|
1071
|
+
# class Address < Shale::Mapper
|
1072
|
+
# attribute :street, Shale::Type::String
|
1073
|
+
# attribute :city, Shale::Type::String
|
1074
|
+
#
|
1075
|
+
# xml do
|
1076
|
+
# root 'Address'
|
1077
|
+
#
|
1078
|
+
# map_element 'Street', to: :street
|
1079
|
+
# map_element 'City', to: :city
|
1080
|
+
# end
|
1081
|
+
# end
|
1082
|
+
# ",
|
1083
|
+
# "person" => "
|
1084
|
+
# require 'shale'
|
1085
|
+
#
|
1086
|
+
# require_relative 'address'
|
1087
|
+
#
|
1088
|
+
# class Person < Shale::Mapper
|
1089
|
+
# attribute :first_name, Shale::Type::String
|
1090
|
+
# attribute :last_name, Shale::Type::String
|
1091
|
+
# attribute :address, Address
|
1092
|
+
#
|
1093
|
+
# xml do
|
1094
|
+
# root 'Person'
|
1095
|
+
#
|
1096
|
+
# map_element 'FirstName', to: :first_name
|
1097
|
+
# map_element 'LastName', to: :last_name
|
1098
|
+
# map_element 'Address', to: :address
|
1099
|
+
# end
|
1100
|
+
# end
|
1101
|
+
# "
|
1102
|
+
# }
|
1103
|
+
```
|
1104
|
+
|
1105
|
+
You can also use a command line tool to do it:
|
1106
|
+
|
1107
|
+
```
|
1108
|
+
$ shaleb -c -f xml -i schema.xml
|
752
1109
|
```
|
753
1110
|
|
754
1111
|
## Contributing
|