jsi 0.4.0 → 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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +15 -0
  4. data/README.md +105 -38
  5. data/lib/jsi/base.rb +349 -155
  6. data/lib/jsi/jsi_coder.rb +5 -4
  7. data/lib/jsi/metaschema_node/bootstrap_schema.rb +100 -0
  8. data/lib/jsi/metaschema_node.rb +156 -129
  9. data/lib/jsi/pathed_node.rb +47 -49
  10. data/lib/jsi/ptr.rb +292 -0
  11. data/lib/jsi/schema/application/child_application/contains.rb +16 -0
  12. data/lib/jsi/schema/application/child_application/draft04.rb +22 -0
  13. data/lib/jsi/schema/application/child_application/draft06.rb +29 -0
  14. data/lib/jsi/schema/application/child_application/draft07.rb +29 -0
  15. data/lib/jsi/schema/application/child_application/items.rb +18 -0
  16. data/lib/jsi/schema/application/child_application/properties.rb +25 -0
  17. data/lib/jsi/schema/application/child_application.rb +40 -0
  18. data/lib/jsi/schema/application/draft04.rb +8 -0
  19. data/lib/jsi/schema/application/draft06.rb +8 -0
  20. data/lib/jsi/schema/application/draft07.rb +8 -0
  21. data/lib/jsi/schema/application/inplace_application/dependencies.rb +28 -0
  22. data/lib/jsi/schema/application/inplace_application/draft04.rb +26 -0
  23. data/lib/jsi/schema/application/inplace_application/draft06.rb +27 -0
  24. data/lib/jsi/schema/application/inplace_application/draft07.rb +33 -0
  25. data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +20 -0
  26. data/lib/jsi/schema/application/inplace_application/ref.rb +18 -0
  27. data/lib/jsi/schema/application/inplace_application/someof.rb +29 -0
  28. data/lib/jsi/schema/application/inplace_application.rb +46 -0
  29. data/lib/jsi/schema/application.rb +12 -0
  30. data/lib/jsi/schema/draft04.rb +14 -0
  31. data/lib/jsi/schema/draft06.rb +14 -0
  32. data/lib/jsi/schema/draft07.rb +14 -0
  33. data/lib/jsi/schema/issue.rb +36 -0
  34. data/lib/jsi/schema/ref.rb +159 -0
  35. data/lib/jsi/schema/schema_ancestor_node.rb +119 -0
  36. data/lib/jsi/schema/validation/array.rb +69 -0
  37. data/lib/jsi/schema/validation/const.rb +20 -0
  38. data/lib/jsi/schema/validation/contains.rb +25 -0
  39. data/lib/jsi/schema/validation/core.rb +39 -0
  40. data/lib/jsi/schema/validation/dependencies.rb +49 -0
  41. data/lib/jsi/schema/validation/draft04/minmax.rb +91 -0
  42. data/lib/jsi/schema/validation/draft04.rb +112 -0
  43. data/lib/jsi/schema/validation/draft06.rb +122 -0
  44. data/lib/jsi/schema/validation/draft07.rb +159 -0
  45. data/lib/jsi/schema/validation/enum.rb +25 -0
  46. data/lib/jsi/schema/validation/ifthenelse.rb +46 -0
  47. data/lib/jsi/schema/validation/items.rb +54 -0
  48. data/lib/jsi/schema/validation/not.rb +20 -0
  49. data/lib/jsi/schema/validation/numeric.rb +121 -0
  50. data/lib/jsi/schema/validation/object.rb +45 -0
  51. data/lib/jsi/schema/validation/pattern.rb +34 -0
  52. data/lib/jsi/schema/validation/properties.rb +101 -0
  53. data/lib/jsi/schema/validation/property_names.rb +32 -0
  54. data/lib/jsi/schema/validation/ref.rb +40 -0
  55. data/lib/jsi/schema/validation/required.rb +27 -0
  56. data/lib/jsi/schema/validation/someof.rb +90 -0
  57. data/lib/jsi/schema/validation/string.rb +47 -0
  58. data/lib/jsi/schema/validation/type.rb +49 -0
  59. data/lib/jsi/schema/validation.rb +51 -0
  60. data/lib/jsi/schema.rb +486 -133
  61. data/lib/jsi/schema_classes.rb +157 -42
  62. data/lib/jsi/schema_registry.rb +141 -0
  63. data/lib/jsi/schema_set.rb +141 -0
  64. data/lib/jsi/simple_wrap.rb +2 -2
  65. data/lib/jsi/typelike_modules.rb +52 -37
  66. data/lib/jsi/util/attr_struct.rb +106 -0
  67. data/lib/jsi/util.rb +141 -25
  68. data/lib/jsi/validation/error.rb +34 -0
  69. data/lib/jsi/validation/result.rb +210 -0
  70. data/lib/jsi/validation.rb +15 -0
  71. data/lib/jsi/version.rb +3 -1
  72. data/lib/jsi.rb +55 -9
  73. data/lib/schemas/json-schema.org/draft-04/schema.rb +8 -3
  74. data/lib/schemas/json-schema.org/draft-06/schema.rb +8 -3
  75. data/lib/schemas/json-schema.org/draft-07/schema.rb +12 -0
  76. data/readme.rb +138 -0
  77. data/{resources}/schemas/json-schema.org/draft-04/schema.json +149 -0
  78. data/{resources}/schemas/json-schema.org/draft-06/schema.json +154 -0
  79. data/{resources}/schemas/json-schema.org/draft-07/schema.json +168 -0
  80. metadata +69 -118
  81. data/.simplecov +0 -3
  82. data/Rakefile.rb +0 -9
  83. data/jsi.gemspec +0 -28
  84. data/lib/jsi/base/to_rb.rb +0 -128
  85. data/lib/jsi/json/node.rb +0 -203
  86. data/lib/jsi/json/pointer.rb +0 -419
  87. data/lib/jsi/json-schema-fragments.rb +0 -61
  88. data/lib/jsi/json.rb +0 -10
  89. data/resources/icons/AGPL-3.0.png +0 -0
  90. data/test/base_array_test.rb +0 -323
  91. data/test/base_hash_test.rb +0 -337
  92. data/test/base_test.rb +0 -486
  93. data/test/jsi_coder_test.rb +0 -85
  94. data/test/jsi_json_arraynode_test.rb +0 -150
  95. data/test/jsi_json_hashnode_test.rb +0 -132
  96. data/test/jsi_json_node_test.rb +0 -257
  97. data/test/jsi_json_pointer_test.rb +0 -102
  98. data/test/jsi_test.rb +0 -11
  99. data/test/jsi_typelike_as_json_test.rb +0 -53
  100. data/test/metaschema_node_test.rb +0 -19
  101. data/test/schema_module_test.rb +0 -21
  102. data/test/schema_test.rb +0 -208
  103. data/test/spreedly_openapi_test.rb +0 -8
  104. data/test/test_helper.rb +0 -97
  105. data/test/util_test.rb +0 -62
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSI
4
+ module Validation
5
+ # a result of validating an instance against schemas which describe it.
6
+ # virtual base class.
7
+ class Result
8
+ include Util::Virtual
9
+
10
+ Builder = Util::AttrStruct[*%w(
11
+ result
12
+ schema
13
+ instance_ptr
14
+ instance_document
15
+ validate_only
16
+ visited_refs
17
+ )]
18
+
19
+ # @private
20
+ # a structure used to build a Result. virtual base class.
21
+ class Builder
22
+ def instance
23
+ instance_ptr.evaluate(instance_document)
24
+ end
25
+
26
+ def schema_issue(*_)
27
+ virtual_method
28
+ end
29
+
30
+ def schema_error(message, keyword = nil)
31
+ schema_issue(:error, message, keyword)
32
+ end
33
+
34
+ def schema_warning(message, keyword = nil)
35
+ schema_issue(:warning, message, keyword)
36
+ end
37
+
38
+ # @param subschema_ptr [JSI::Ptr, #to_ary]
39
+ # @return [JSI::Validation::Result]
40
+ def inplace_subschema_validate(subschema_ptr)
41
+ subresult = schema.subschema(subschema_ptr).internal_validate_instance(
42
+ instance_ptr,
43
+ instance_document,
44
+ validate_only: validate_only,
45
+ visited_refs: visited_refs,
46
+ )
47
+ merge_schema_issues(subresult)
48
+ subresult
49
+ end
50
+
51
+ # @param subschema_ptr [JSI::Ptr, #to_ary]
52
+ # @param subinstance_ptr [JSI::Ptr, #to_ary]
53
+ # @return [JSI::Validation::Result]
54
+ def child_subschema_validate(subschema_ptr, subinstance_ptr)
55
+ subresult = schema.subschema(subschema_ptr).internal_validate_instance(
56
+ instance_ptr + subinstance_ptr,
57
+ instance_document,
58
+ validate_only: validate_only,
59
+ )
60
+ merge_schema_issues(subresult)
61
+ subresult
62
+ end
63
+
64
+ # @param other_result [JSI::Validation::Result]
65
+ # @return [void]
66
+ def merge_schema_issues(other_result)
67
+ unless validate_only
68
+ # schema_issues are always merged from subschema results (not depending on validation results)
69
+ result.schema_issues.merge(other_result.schema_issues)
70
+ end
71
+ nil
72
+ end
73
+ end
74
+
75
+ def builder(schema, instance_ptr, instance_document, validate_only, visited_refs)
76
+ self.class::Builder.new(
77
+ result: self,
78
+ schema: schema,
79
+ instance_ptr: instance_ptr,
80
+ instance_document: instance_document,
81
+ validate_only: validate_only,
82
+ visited_refs: visited_refs,
83
+ )
84
+ end
85
+
86
+ # is the instance valid against its schemas?
87
+ # @return [Boolean]
88
+ def valid?
89
+ # :nocov:
90
+ virtual_method
91
+ # :nocov:
92
+ end
93
+
94
+ include Util::FingerprintHash
95
+ end
96
+
97
+ # a full result of validating an instance against its schemas, with each validation error
98
+ class FullResult < Result
99
+ # @private
100
+ class Builder < Result::Builder
101
+ def validate(
102
+ valid,
103
+ message,
104
+ keyword: nil,
105
+ results: []
106
+ )
107
+ results.each { |res| result.schema_issues.merge(res.schema_issues) }
108
+ if !valid
109
+ results.each { |res| result.validation_errors.merge(res.validation_errors) }
110
+ result.validation_errors << Validation::Error.new({
111
+ message: message,
112
+ keyword: keyword,
113
+ schema: schema,
114
+ instance_ptr: instance_ptr,
115
+ instance_document: instance_document,
116
+ })
117
+ end
118
+ end
119
+
120
+ def schema_issue(level, message, keyword = nil)
121
+ result.schema_issues << Schema::Issue.new({
122
+ level: level,
123
+ message: message,
124
+ keyword: keyword,
125
+ schema: schema,
126
+ })
127
+ end
128
+ end
129
+
130
+ def initialize
131
+ @validation_errors = Set.new
132
+ @schema_issues = Set.new
133
+ end
134
+
135
+ attr_reader :validation_errors
136
+ attr_reader :schema_issues
137
+
138
+ def valid?
139
+ validation_errors.empty?
140
+ end
141
+
142
+ def freeze
143
+ @validation_errors.each(&:freeze)
144
+ @schema_issues.each(&:freeze)
145
+ @validation_errors.freeze
146
+ @schema_issues.freeze
147
+ super
148
+ end
149
+
150
+ def merge(result)
151
+ unless result.is_a?(FullResult)
152
+ raise(TypeError, "not a #{FullResult.name}: #{result.pretty_inspect.chomp}")
153
+ end
154
+ validation_errors.merge(result.validation_errors)
155
+ schema_issues.merge(result.schema_issues)
156
+ self
157
+ end
158
+
159
+ def +(result)
160
+ FullResult.new.merge(self).merge(result)
161
+ end
162
+
163
+ # @private
164
+ def jsi_fingerprint
165
+ {
166
+ class: self.class,
167
+ validation_errors: validation_errors,
168
+ schema_issues: schema_issues,
169
+ }
170
+ end
171
+ end
172
+
173
+ # a result indicating only whether an instance is valid against its schemas
174
+ class ValidityResult < Result
175
+ # @private
176
+ class Builder < Result::Builder
177
+ def validate(
178
+ valid,
179
+ message,
180
+ keyword: nil,
181
+ results: []
182
+ )
183
+ if !valid
184
+ throw(:jsi_validation_result, INVALID)
185
+ end
186
+ end
187
+
188
+ def schema_issue(*_)
189
+ # noop
190
+ end
191
+ end
192
+
193
+ def initialize(valid)
194
+ @valid = valid
195
+ end
196
+
197
+ def valid?
198
+ @valid
199
+ end
200
+
201
+ # @private
202
+ def jsi_fingerprint
203
+ {
204
+ class: self.class,
205
+ valid: valid?,
206
+ }
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSI
4
+ module Validation
5
+ autoload :Error, 'jsi/validation/error'
6
+
7
+ autoload :Result, 'jsi/validation/result'
8
+ autoload :FullResult, 'jsi/validation/result'
9
+ autoload :ValidityResult, 'jsi/validation/result'
10
+
11
+ VALID = ValidityResult.new(true).freeze
12
+
13
+ INVALID = ValidityResult.new(false).freeze
14
+ end
15
+ end
data/lib/jsi/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module JSI
2
- VERSION = "0.4.0".freeze
4
+ VERSION = "0.6.0".freeze
3
5
  end
data/lib/jsi.rb CHANGED
@@ -5,10 +5,9 @@ require "pp"
5
5
  require "set"
6
6
  require "json"
7
7
  require "pathname"
8
+ require "bigdecimal"
8
9
  require "addressable/uri"
9
10
 
10
- require "jsi/json-schema-fragments"
11
-
12
11
  require "jsi/util"
13
12
  require "jsi/typelike_modules"
14
13
 
@@ -21,30 +20,77 @@ module JSI
21
20
  class Bug < NotImplementedError
22
21
  end
23
22
 
23
+ # @private
24
24
  ROOT_PATH = Pathname.new(__FILE__).dirname.parent.expand_path
25
- RESOURCES_PATH = ROOT_PATH.join('resources')
26
25
 
27
- autoload :JSON, 'jsi/json'
26
+ # @private
27
+ RESOURCES_PATH = ROOT_PATH.join('{resources}')
28
+
29
+ # @private
30
+ SCHEMAS_PATH = RESOURCES_PATH.join('schemas')
31
+
32
+ autoload :Ptr, 'jsi/ptr'
33
+
34
+ # @private
35
+ # @deprecated
36
+ module JSON
37
+ Pointer = Ptr
38
+ end
39
+
28
40
  autoload :PathedNode, 'jsi/pathed_node'
29
41
  autoload :Typelike, 'jsi/typelike_modules'
30
42
  autoload :Hashlike, 'jsi/typelike_modules'
31
43
  autoload :Arraylike, 'jsi/typelike_modules'
32
44
  autoload :Schema, 'jsi/schema'
45
+ autoload :SchemaSet, 'jsi/schema_set'
33
46
  autoload :Base, 'jsi/base'
34
47
  autoload :Metaschema, 'jsi/metaschema'
35
48
  autoload :MetaschemaNode, 'jsi/metaschema_node'
36
49
  autoload :SchemaClasses, 'jsi/schema_classes'
50
+ autoload :SchemaRegistry, 'jsi/schema_registry'
51
+ autoload :Validation, 'jsi/validation'
37
52
  autoload :JSICoder, 'jsi/jsi_coder'
38
53
 
39
54
  autoload :JSONSchemaOrgDraft04, 'schemas/json-schema.org/draft-04/schema'
40
55
  autoload :JSONSchemaOrgDraft06, 'schemas/json-schema.org/draft-06/schema'
56
+ autoload :JSONSchemaOrgDraft07, 'schemas/json-schema.org/draft-07/schema'
41
57
 
42
58
  autoload :SimpleWrap, 'jsi/simple_wrap'
43
59
 
44
- # @param schemas [Enumerable<JSI::Schema, #to_hash, Boolean>] schemas to represent with the class
45
- # @return [Class subclassing JSI::Base] a JSI class which represents the given schemas.
46
- # an instance of the class represents a JSON Schema instance described by all of the given schemas.
47
- def self.class_for_schemas(*schemas)
48
- SchemaClasses.class_for_schemas(*schemas)
60
+ # instantiates a given schema object as a JSI Schema.
61
+ #
62
+ # see {JSI::Schema.new_schema}
63
+ #
64
+ # @param (see JSI::Schema.new_schema)
65
+ # @return (see JSI::Schema.new_schema)
66
+ def self.new_schema(schema_object, **kw)
67
+ JSI::Schema.new_schema(schema_object, **kw)
68
+ end
69
+
70
+ # instantiates a given schema object as a JSI Schema and returns its JSI Schema Module.
71
+ #
72
+ # shortcut to chain {JSI::Schema.new_schema} + {Schema#jsi_schema_module}.
73
+ #
74
+ # @param (see JSI::Schema.new_schema)
75
+ # @return [Module, JSI::SchemaModule] the JSI Schema Module of the schema
76
+ def self.new_schema_module(schema_object, **kw)
77
+ JSI::Schema.new_schema(schema_object, **kw).jsi_schema_module
78
+ end
79
+
80
+ # @private @deprecated
81
+ def self.class_for_schemas(schemas)
82
+ SchemaClasses.class_for_schemas(schemas.map { |schema| JSI.new_schema(schema) })
83
+ end
84
+
85
+ # `JSI.schema_registry` is the {JSI::SchemaRegistry} in which schemas are registered.
86
+ #
87
+ # @return [JSI::SchemaRegistry]
88
+ def self.schema_registry
89
+ return @schema_registry if instance_variable_defined?(:@schema_registry)
90
+ @schema_registry = SchemaRegistry.new
49
91
  end
50
92
  end
93
+
94
+ JSI.schema_registry.autoload_uri("http://json-schema.org/draft-04/schema") { JSI::JSONSchemaOrgDraft04.schema }
95
+ JSI.schema_registry.autoload_uri("http://json-schema.org/draft-06/schema") { JSI::JSONSchemaOrgDraft06.schema }
96
+ JSI.schema_registry.autoload_uri("http://json-schema.org/draft-07/schema") { JSI::JSONSchemaOrgDraft07.schema }
@@ -1,7 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JSI
4
- schema_id = 'http://json-schema.org/draft-04/schema'
5
- schema_content = ::JSON.parse(File.read(::JSON::Validator.validators[schema_id].metaschema))
6
- JSONSchemaOrgDraft04 = MetaschemaNode.new(schema_content).jsi_schema_module
4
+ metaschema_document = ::JSON.parse(SCHEMAS_PATH.join('json-schema.org/draft-04/schema.json').read)
5
+ JSONSchemaOrgDraft04 = MetaschemaNode.new(metaschema_document,
6
+ metaschema_instance_modules: [JSI::Schema::Draft04],
7
+ ).jsi_schema_module
8
+
9
+ # the JSI schema module for `http://json-schema.org/draft-04/schema`
10
+ module JSONSchemaOrgDraft04
11
+ end
7
12
  end
@@ -1,7 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JSI
4
- schema_id = 'http://json-schema.org/draft/schema' # I don't know why this is not http://json-schema.org/draft-06/schema
5
- schema_content = ::JSON.parse(File.read(::JSON::Validator.validators[schema_id].metaschema))
6
- JSONSchemaOrgDraft06 = MetaschemaNode.new(schema_content).jsi_schema_module
4
+ metaschema_document = ::JSON.parse(SCHEMAS_PATH.join('json-schema.org/draft-06/schema.json').read)
5
+ JSONSchemaOrgDraft06 = MetaschemaNode.new(metaschema_document,
6
+ metaschema_instance_modules: [JSI::Schema::Draft06],
7
+ ).jsi_schema_module
8
+
9
+ # the JSI schema module for `http://json-schema.org/draft-06/schema`
10
+ module JSONSchemaOrgDraft06
11
+ end
7
12
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSI
4
+ metaschema_document = ::JSON.parse(SCHEMAS_PATH.join('json-schema.org/draft-07/schema.json').read)
5
+ JSONSchemaOrgDraft07 = MetaschemaNode.new(metaschema_document,
6
+ metaschema_instance_modules: [JSI::Schema::Draft07],
7
+ ).jsi_schema_module
8
+
9
+ # the JSI schema module for `http://json-schema.org/draft-07/schema`
10
+ module JSONSchemaOrgDraft07
11
+ end
12
+ end
data/readme.rb ADDED
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # a small script following the code samples in the README
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
7
+ require 'jsi'
8
+
9
+ puts "creating a schema and assigning its schema module to a constant"
10
+ puts
11
+
12
+ contact_schema = JSI.new_schema({
13
+ "$schema" => "http://json-schema.org/draft-07/schema",
14
+ "description" => "A Contact",
15
+ "type" => "object",
16
+ "properties" => {
17
+ "name" => {
18
+ "type" => "string",
19
+ },
20
+ "phone" => {
21
+ "type" => "array",
22
+ "items" => {
23
+ "type" => "object",
24
+ "properties" => {
25
+ "location" => {
26
+ "type" => "string",
27
+ },
28
+ "number" => {
29
+ "type" => "string",
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ })
36
+
37
+ print 'contact_schema: '
38
+ pp contact_schema
39
+
40
+ print 'contact_schema.jsi_schema_module: '
41
+ pp contact_schema.jsi_schema_module
42
+
43
+ puts "constant assignment: Contact = contact_schema.jsi_schema_module"
44
+ Contact = contact_schema.jsi_schema_module
45
+
46
+ print 'contact_schema.jsi_schema_module: '
47
+ pp contact_schema.jsi_schema_module
48
+
49
+ puts
50
+ puts "creating and using an instance described by the schema"
51
+ puts
52
+
53
+ bill = Contact.new_jsi({
54
+ "name" => "bill",
55
+ "phone" => [
56
+ {
57
+ "location" => "home",
58
+ "number" => "555",
59
+ }
60
+ ],
61
+ "nickname" => "big b",
62
+ })
63
+
64
+ print 'bill: '
65
+ pp bill
66
+
67
+ print 'bill.name: '
68
+ pp bill.name
69
+
70
+ print 'bill.phone.map(&:location): '
71
+ pp bill.phone.map(&:location)
72
+
73
+ print 'bill.jsi_valid?: '
74
+ pp bill.jsi_valid?
75
+
76
+ bad = Contact.new_jsi({'phone' => [{'number' => [5, 5, 5]}]})
77
+
78
+ print 'bad: '
79
+ pp bad
80
+
81
+ print 'bad.phone.jsi_validate: '
82
+ pp bad.phone.jsi_validate
83
+
84
+ print 'bill.transform_values(&:size): '
85
+ pp bill.transform_values(&:size)
86
+
87
+ print "bill['nickname']: "
88
+ pp bill['nickname']
89
+
90
+ puts
91
+ puts "OOP: application-defined methods on schema modules apply to their instances"
92
+ puts
93
+
94
+ module Contact
95
+ def phone_numbers
96
+ phone.map(&:number)
97
+ end
98
+ def name
99
+ super + ' esq.'
100
+ end
101
+ def name=(name)
102
+ super(name.chomp(' esq.'))
103
+ end
104
+ end
105
+
106
+ print 'bill.name: '
107
+ pp bill.name
108
+
109
+ puts "bill.name = 'rob esq.'"
110
+ bill.name = 'rob esq.'
111
+
112
+ print "bill['name']: "
113
+ pp bill['name']
114
+
115
+ print 'bill.phone_numbers: '
116
+ pp bill.phone_numbers
117
+
118
+ puts
119
+ puts "OOP on subschemas"
120
+ puts
121
+
122
+ print "Contact.properties['phone'].items: "
123
+ pp Contact.properties['phone'].items
124
+
125
+ module Contact
126
+ Phone = properties['phone'].items
127
+ module Phone
128
+ def number_with_dashes
129
+ number.split(//).join('-')
130
+ end
131
+ end
132
+ end
133
+
134
+ print "Contact.properties['phone'].items: "
135
+ pp Contact.properties['phone'].items
136
+
137
+ print 'bill.phone.first.number_with_dashes: '
138
+ pp bill.phone.first.number_with_dashes
@@ -0,0 +1,149 @@
1
+ {
2
+ "id": "http://json-schema.org/draft-04/schema#",
3
+ "$schema": "http://json-schema.org/draft-04/schema#",
4
+ "description": "Core schema meta-schema",
5
+ "definitions": {
6
+ "schemaArray": {
7
+ "type": "array",
8
+ "minItems": 1,
9
+ "items": { "$ref": "#" }
10
+ },
11
+ "positiveInteger": {
12
+ "type": "integer",
13
+ "minimum": 0
14
+ },
15
+ "positiveIntegerDefault0": {
16
+ "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ]
17
+ },
18
+ "simpleTypes": {
19
+ "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
20
+ },
21
+ "stringArray": {
22
+ "type": "array",
23
+ "items": { "type": "string" },
24
+ "minItems": 1,
25
+ "uniqueItems": true
26
+ }
27
+ },
28
+ "type": "object",
29
+ "properties": {
30
+ "id": {
31
+ "type": "string"
32
+ },
33
+ "$schema": {
34
+ "type": "string"
35
+ },
36
+ "title": {
37
+ "type": "string"
38
+ },
39
+ "description": {
40
+ "type": "string"
41
+ },
42
+ "default": {},
43
+ "multipleOf": {
44
+ "type": "number",
45
+ "minimum": 0,
46
+ "exclusiveMinimum": true
47
+ },
48
+ "maximum": {
49
+ "type": "number"
50
+ },
51
+ "exclusiveMaximum": {
52
+ "type": "boolean",
53
+ "default": false
54
+ },
55
+ "minimum": {
56
+ "type": "number"
57
+ },
58
+ "exclusiveMinimum": {
59
+ "type": "boolean",
60
+ "default": false
61
+ },
62
+ "maxLength": { "$ref": "#/definitions/positiveInteger" },
63
+ "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" },
64
+ "pattern": {
65
+ "type": "string",
66
+ "format": "regex"
67
+ },
68
+ "additionalItems": {
69
+ "anyOf": [
70
+ { "type": "boolean" },
71
+ { "$ref": "#" }
72
+ ],
73
+ "default": {}
74
+ },
75
+ "items": {
76
+ "anyOf": [
77
+ { "$ref": "#" },
78
+ { "$ref": "#/definitions/schemaArray" }
79
+ ],
80
+ "default": {}
81
+ },
82
+ "maxItems": { "$ref": "#/definitions/positiveInteger" },
83
+ "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" },
84
+ "uniqueItems": {
85
+ "type": "boolean",
86
+ "default": false
87
+ },
88
+ "maxProperties": { "$ref": "#/definitions/positiveInteger" },
89
+ "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" },
90
+ "required": { "$ref": "#/definitions/stringArray" },
91
+ "additionalProperties": {
92
+ "anyOf": [
93
+ { "type": "boolean" },
94
+ { "$ref": "#" }
95
+ ],
96
+ "default": {}
97
+ },
98
+ "definitions": {
99
+ "type": "object",
100
+ "additionalProperties": { "$ref": "#" },
101
+ "default": {}
102
+ },
103
+ "properties": {
104
+ "type": "object",
105
+ "additionalProperties": { "$ref": "#" },
106
+ "default": {}
107
+ },
108
+ "patternProperties": {
109
+ "type": "object",
110
+ "additionalProperties": { "$ref": "#" },
111
+ "default": {}
112
+ },
113
+ "dependencies": {
114
+ "type": "object",
115
+ "additionalProperties": {
116
+ "anyOf": [
117
+ { "$ref": "#" },
118
+ { "$ref": "#/definitions/stringArray" }
119
+ ]
120
+ }
121
+ },
122
+ "enum": {
123
+ "type": "array",
124
+ "minItems": 1,
125
+ "uniqueItems": true
126
+ },
127
+ "type": {
128
+ "anyOf": [
129
+ { "$ref": "#/definitions/simpleTypes" },
130
+ {
131
+ "type": "array",
132
+ "items": { "$ref": "#/definitions/simpleTypes" },
133
+ "minItems": 1,
134
+ "uniqueItems": true
135
+ }
136
+ ]
137
+ },
138
+ "format": { "type": "string" },
139
+ "allOf": { "$ref": "#/definitions/schemaArray" },
140
+ "anyOf": { "$ref": "#/definitions/schemaArray" },
141
+ "oneOf": { "$ref": "#/definitions/schemaArray" },
142
+ "not": { "$ref": "#" }
143
+ },
144
+ "dependencies": {
145
+ "exclusiveMaximum": [ "maximum" ],
146
+ "exclusiveMinimum": [ "minimum" ]
147
+ },
148
+ "default": {}
149
+ }