shale 0.3.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|