jsi 0.0.2 → 0.0.3
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 +6 -0
- data/lib/jsi/base.rb +39 -26
- data/lib/jsi/schema.rb +27 -0
- data/lib/jsi/util.rb +1 -0
- data/lib/jsi/version.rb +1 -1
- data/test/base_array_test.rb +55 -0
- data/test/base_hash_test.rb +59 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12a262c5b9ec6c22d16c8e4f5cb983c92266d165964a120ffcd72f7e0bd877d1
|
4
|
+
data.tar.gz: 3e4671dda156d3d8073e9f7af42e3335af8f3482719a0495d4f57a2dfaaf12c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f9c9816756bb70c16498d2ba503c7b0148533b37ae065d8426e654a0644066db6108a6a7d79789bb039f4911432b4273ca85d6a08a47783d0e992af06e248c2
|
7
|
+
data.tar.gz: c9859fffe7cffbdde822530c828db5344cefa12e2b94eef5d3732d88dca741db5e93414c2800d681fba4555b6694d5bf873cdee08ccbfbce293f3e159ac2749e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# v0.0.3
|
2
|
+
|
3
|
+
- JSI::Base returns an instance of the default value for the schema if applicable
|
4
|
+
- JSI::Base instance method #class_for_schema may be overridden by subclasses
|
5
|
+
- bugfixes and internal refactoring
|
6
|
+
|
1
7
|
# v0.0.2
|
2
8
|
|
3
9
|
- JSI::JSON::Node and other utilities duck-type better with #to_hash and #to_ary
|
data/lib/jsi/base.rb
CHANGED
@@ -67,14 +67,14 @@ module JSI
|
|
67
67
|
# a Node already).
|
68
68
|
#
|
69
69
|
# @param instance [Object] the JSON Schema instance being represented
|
70
|
-
# @param
|
71
|
-
# from which this JSI originated
|
72
|
-
def initialize(instance,
|
70
|
+
# @param ancestor [JSI::Base] for internal use, specifies an ancestor
|
71
|
+
# from which this JSI originated to calculate #parents
|
72
|
+
def initialize(instance, ancestor: nil)
|
73
73
|
unless respond_to?(:schema)
|
74
74
|
raise(TypeError, "cannot instantiate #{self.class.inspect} which has no method #schema. please use JSI.class_for_schema")
|
75
75
|
end
|
76
76
|
|
77
|
-
@
|
77
|
+
@ancestor = ancestor || self
|
78
78
|
self.instance = instance
|
79
79
|
|
80
80
|
if @instance.is_a?(JSI::JSON::HashNode)
|
@@ -87,6 +87,9 @@ module JSI
|
|
87
87
|
# the instance of the json-schema. this is a JSI::JSON::Node.
|
88
88
|
attr_reader :instance
|
89
89
|
|
90
|
+
# a JSI which is an ancestor of this
|
91
|
+
attr_reader :ancestor
|
92
|
+
|
90
93
|
# each is overridden by BaseHash or BaseArray when appropriate. the base
|
91
94
|
# #each is not actually implemented, along with all the methods of Enumerable.
|
92
95
|
def each
|
@@ -99,8 +102,8 @@ module JSI
|
|
99
102
|
#
|
100
103
|
# @return [Array<JSI::Base>]
|
101
104
|
def parents
|
102
|
-
parent = @
|
103
|
-
(@
|
105
|
+
parent = @ancestor
|
106
|
+
(@ancestor.instance.path.size...self.instance.path.size).map do |i|
|
104
107
|
parent.tap do
|
105
108
|
parent = parent[self.instance.path[i]]
|
106
109
|
end
|
@@ -123,7 +126,7 @@ module JSI
|
|
123
126
|
if derefed.object_id == instance.object_id
|
124
127
|
self
|
125
128
|
else
|
126
|
-
self.class.new(derefed,
|
129
|
+
self.class.new(derefed, ancestor: @ancestor)
|
127
130
|
end
|
128
131
|
end
|
129
132
|
|
@@ -136,7 +139,7 @@ module JSI
|
|
136
139
|
# @return [JSI::Base subclass the same as self] the modified copy of self
|
137
140
|
def modified_copy(&block)
|
138
141
|
modified_instance = instance.modified_copy(&block)
|
139
|
-
self.class.new(modified_instance,
|
142
|
+
self.class.new(modified_instance, ancestor: @ancestor)
|
140
143
|
end
|
141
144
|
|
142
145
|
def fragment
|
@@ -228,6 +231,12 @@ module JSI
|
|
228
231
|
instance[subscript] = value
|
229
232
|
end
|
230
233
|
end
|
234
|
+
|
235
|
+
# this is an instance method in order to allow subclasses of JSI classes to
|
236
|
+
# override it to point to other subclasses corresponding to other schemas.
|
237
|
+
def class_for_schema(schema)
|
238
|
+
JSI.class_for_schema(schema)
|
239
|
+
end
|
231
240
|
end
|
232
241
|
|
233
242
|
# this module is just a namespace for schema classes.
|
@@ -247,13 +256,7 @@ module JSI
|
|
247
256
|
|
248
257
|
# see {JSI.class_for_schema}
|
249
258
|
def SchemaClasses.class_for_schema(schema_object)
|
250
|
-
|
251
|
-
schema__ = schema_object
|
252
|
-
else
|
253
|
-
schema__ = JSI::Schema.new(schema_object)
|
254
|
-
end
|
255
|
-
|
256
|
-
memoize(:class_for_schema, schema__) do |schema_|
|
259
|
+
memoize(:class_for_schema, JSI::Schema.from_object(schema_object)) do |schema_|
|
257
260
|
begin
|
258
261
|
begin
|
259
262
|
Class.new(Base).instance_exec(schema_) do |schema|
|
@@ -284,13 +287,7 @@ module JSI
|
|
284
287
|
# class will be defined. users should use #[] and #[]= to access properties
|
285
288
|
# whose names conflict with existing methods.
|
286
289
|
def SchemaClasses.module_for_schema(schema_object)
|
287
|
-
|
288
|
-
schema__ = schema_object
|
289
|
-
else
|
290
|
-
schema__ = JSI::Schema.new(schema_object)
|
291
|
-
end
|
292
|
-
|
293
|
-
memoize(:module_for_schema, schema__) do |schema_|
|
290
|
+
memoize(:module_for_schema, JSI::Schema.from_object(schema_object)) do |schema_|
|
294
291
|
Module.new.tap do |m|
|
295
292
|
m.instance_exec(schema_) do |schema|
|
296
293
|
define_method(:schema) { schema }
|
@@ -369,8 +366,16 @@ module JSI
|
|
369
366
|
property_schema = schema.subschema_for_property(property_name)
|
370
367
|
property_schema = property_schema && property_schema.match_to_instance(instance[property_name])
|
371
368
|
|
372
|
-
if property_schema &&
|
373
|
-
|
369
|
+
if !instance.key?(property_name) && property_schema && property_schema.schema_object.key?('default')
|
370
|
+
# use the default value
|
371
|
+
default = property_schema.schema_object['default']
|
372
|
+
if default.respond_to?(:to_hash) || default.respond_to?(:to_ary)
|
373
|
+
class_for_schema(property_schema).new(default, ancestor: @ancestor)
|
374
|
+
else
|
375
|
+
default
|
376
|
+
end
|
377
|
+
elsif property_schema && (instance[property_name].respond_to?(:to_hash) || instance[property_name].respond_to?(:to_ary))
|
378
|
+
class_for_schema(property_schema).new(instance[property_name], ancestor: @ancestor)
|
374
379
|
else
|
375
380
|
instance[property_name]
|
376
381
|
end
|
@@ -426,8 +431,16 @@ module JSI
|
|
426
431
|
index_schema = schema.subschema_for_index(i)
|
427
432
|
index_schema = index_schema && index_schema.match_to_instance(instance[i])
|
428
433
|
|
429
|
-
if index_schema &&
|
430
|
-
|
434
|
+
if !instance.each_index.to_a.include?(i) && index_schema && index_schema.schema_object.key?('default')
|
435
|
+
# use the default value
|
436
|
+
default = index_schema.schema_object['default']
|
437
|
+
if default.respond_to?(:to_hash) || default.respond_to?(:to_ary)
|
438
|
+
class_for_schema(index_schema).new(default, ancestor: @ancestor)
|
439
|
+
else
|
440
|
+
default
|
441
|
+
end
|
442
|
+
elsif index_schema && (instance[i].respond_to?(:to_hash) || instance[i].respond_to?(:to_ary))
|
443
|
+
class_for_schema(index_schema).new(instance[i], ancestor: @ancestor)
|
431
444
|
else
|
432
445
|
instance[i]
|
433
446
|
end
|
data/lib/jsi/schema.rb
CHANGED
@@ -7,6 +7,16 @@ module JSI
|
|
7
7
|
class Schema
|
8
8
|
include Memoize
|
9
9
|
|
10
|
+
class << self
|
11
|
+
def from_object(schema_object)
|
12
|
+
if schema_object.is_a?(Schema)
|
13
|
+
schema_object
|
14
|
+
else
|
15
|
+
new(schema_object)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
10
20
|
# initializes a schema from a given JSI::Base, JSI::JSON::Node, or hash.
|
11
21
|
# @param schema_object [JSI::Base, #to_hash] the schema
|
12
22
|
def initialize(schema_object)
|
@@ -118,6 +128,7 @@ module JSI
|
|
118
128
|
# matching allOf is questionable. all of the schemas must be matched but we just return the first match.
|
119
129
|
# there isn't really a better answer with the current implementation. merging the schemas together
|
120
130
|
# is a thought but is not practical.
|
131
|
+
instance = instance.deref if instance.is_a?(JSI::JSON::Node)
|
121
132
|
%w(oneOf allOf anyOf).select { |k| schema_node[k].respond_to?(:to_ary) }.each do |someof_key|
|
122
133
|
schema_node[someof_key].map(&:deref).map do |someof_node|
|
123
134
|
someof_schema = self.class.new(someof_node)
|
@@ -201,6 +212,22 @@ module JSI
|
|
201
212
|
end
|
202
213
|
end
|
203
214
|
|
215
|
+
def default_value
|
216
|
+
if schema_node.key?('default')
|
217
|
+
if schema_node['default'].respond_to?(:to_ary) || schema_node['default'].respond_to?(:to_hash)
|
218
|
+
schema_class.new(schema_node['default'])
|
219
|
+
else
|
220
|
+
schema_node['default']
|
221
|
+
end
|
222
|
+
else
|
223
|
+
nil
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def default_value?
|
228
|
+
schema_node.key?('default')
|
229
|
+
end
|
230
|
+
|
204
231
|
# @return [Array<String>] array of schema validation error messages for
|
205
232
|
# the given instance against this schema
|
206
233
|
def fully_validate(instance)
|
data/lib/jsi/util.rb
CHANGED
data/lib/jsi/version.rb
CHANGED
data/test/base_array_test.rb
CHANGED
@@ -20,6 +20,61 @@ describe JSI::BaseArray do
|
|
20
20
|
let(:class_for_schema) { JSI.class_for_schema(schema) }
|
21
21
|
let(:subject) { class_for_schema.new(instance) }
|
22
22
|
|
23
|
+
describe '#[] with a default that is a basic type' do
|
24
|
+
let(:schema_content) do
|
25
|
+
{
|
26
|
+
'type' => 'array',
|
27
|
+
'items' => {'default' => 'foo'},
|
28
|
+
}
|
29
|
+
end
|
30
|
+
describe 'default value' do
|
31
|
+
let(:document) { [1] }
|
32
|
+
it 'returns the default value' do
|
33
|
+
assert_equal('foo', subject[2])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
describe 'nondefault value (basic type)' do
|
37
|
+
let(:document) { ['who'] }
|
38
|
+
it 'returns the nondefault value' do
|
39
|
+
assert_equal('who', subject[0])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
describe 'nondefault value (nonbasic type)' do
|
43
|
+
let(:document) { [[2]] }
|
44
|
+
it 'returns the nondefault value' do
|
45
|
+
assert_instance_of(JSI.class_for_schema(schema['items']), subject[0])
|
46
|
+
assert_equal([2], subject[0].as_json)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
describe '#[] with a default that is a nonbasic type' do
|
51
|
+
let(:schema_content) do
|
52
|
+
{
|
53
|
+
'type' => 'array',
|
54
|
+
'items' => {'default' => {'foo' => 2}},
|
55
|
+
}
|
56
|
+
end
|
57
|
+
describe 'default value' do
|
58
|
+
let(:document) { [{'bar' => 3}] }
|
59
|
+
it 'returns the default value' do
|
60
|
+
assert_instance_of(JSI.class_for_schema(schema['items']), subject[1])
|
61
|
+
assert_equal({'foo' => 2}, subject[1].as_json)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
describe 'nondefault value (basic type)' do
|
65
|
+
let(:document) { [true, 'who'] }
|
66
|
+
it 'returns the nondefault value' do
|
67
|
+
assert_equal('who', subject[1])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
describe 'nondefault value (nonbasic type)' do
|
71
|
+
let(:document) { [true, [2]] }
|
72
|
+
it 'returns the nondefault value' do
|
73
|
+
assert_instance_of(JSI.class_for_schema(schema['items']), subject[1])
|
74
|
+
assert_equal([2], subject[1].as_json)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
23
78
|
describe 'arraylike []=' do
|
24
79
|
it 'sets an index' do
|
25
80
|
orig_2 = subject[2]
|
data/test/base_hash_test.rb
CHANGED
@@ -19,6 +19,65 @@ describe JSI::BaseHash do
|
|
19
19
|
let(:class_for_schema) { JSI.class_for_schema(schema) }
|
20
20
|
let(:subject) { class_for_schema.new(instance) }
|
21
21
|
|
22
|
+
describe '#[] with a default that is a basic type' do
|
23
|
+
let(:schema_content) do
|
24
|
+
{
|
25
|
+
'type' => 'object',
|
26
|
+
'properties' => {
|
27
|
+
'foo' => {'default' => 'foo'},
|
28
|
+
},
|
29
|
+
}
|
30
|
+
end
|
31
|
+
describe 'default value' do
|
32
|
+
let(:document) { {'bar' => 3} }
|
33
|
+
it 'returns the default value' do
|
34
|
+
assert_equal('foo', subject.foo)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
describe 'nondefault value (basic type)' do
|
38
|
+
let(:document) { {'foo' => 'who'} }
|
39
|
+
it 'returns the nondefault value' do
|
40
|
+
assert_equal('who', subject.foo)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
describe 'nondefault value (nonbasic type)' do
|
44
|
+
let(:document) { {'foo' => [2]} }
|
45
|
+
it 'returns the nondefault value' do
|
46
|
+
assert_instance_of(JSI.class_for_schema(schema['properties']['foo']), subject.foo)
|
47
|
+
assert_equal([2], subject.foo.as_json)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
describe '#[] with a default that is a nonbasic type' do
|
52
|
+
let(:schema_content) do
|
53
|
+
{
|
54
|
+
'type' => 'object',
|
55
|
+
'properties' => {
|
56
|
+
'foo' => {'default' => {'foo' => 2}},
|
57
|
+
},
|
58
|
+
}
|
59
|
+
end
|
60
|
+
describe 'default value' do
|
61
|
+
let(:document) { {'bar' => 3} }
|
62
|
+
it 'returns the default value' do
|
63
|
+
assert_instance_of(JSI.class_for_schema(schema['properties']['foo']), subject.foo)
|
64
|
+
assert_equal({'foo' => 2}, subject.foo.as_json)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
describe 'nondefault value (basic type)' do
|
68
|
+
let(:document) { {'foo' => 'who'} }
|
69
|
+
it 'returns the nondefault value' do
|
70
|
+
assert_equal('who', subject.foo)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
describe 'nondefault value (nonbasic type)' do
|
74
|
+
let(:document) { {'foo' => [2]} }
|
75
|
+
it 'returns the nondefault value' do
|
76
|
+
assert_instance_of(JSI.class_for_schema(schema['properties']['foo']), subject.foo)
|
77
|
+
assert_equal([2], subject.foo.as_json)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
22
81
|
describe 'hashlike []=' do
|
23
82
|
it 'sets a property' do
|
24
83
|
orig_foo = subject['foo']
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ethan
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json-schema
|