json_schemer 0.2.13 → 0.2.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e21ec6fd7dcbc28003dfab561b6bf370703ff602abc3b31fa579f5898e5934c6
4
- data.tar.gz: 89ca6ea9b2400fcaafc3eae438077af0cc881f19bd40646c8bc74c3772bcae89
3
+ metadata.gz: 426a95173deee91594b5ad1df05dac15ea3c90bac6e17b3136a7170744555c50
4
+ data.tar.gz: 25268e7f5cb108245aad3d112624eee96774fe8820eda5e24a4f91d97d91e676
5
5
  SHA512:
6
- metadata.gz: b12e2e504bd9222f9f86a5f54d7e2c9a0cc9d323d49d9d3b3f11161fdfefb86ce1080c62bf07b0de462d28bced42276bb6faaa3943c2ce1faee1d3f61e8f3c1f
7
- data.tar.gz: f3157b1e89c4eb89cc9727cd93087b518d78ae05fc46c0fe8f6ddc81815dee55d6fa576b5b46bd112479466d134ec0b24a2f75f58e6f80073435600ce796edd9
6
+ metadata.gz: 5534a623dfece170bd27bbb2cbc34978e9e81c075ddad60213d8ce4538d50a6ee119b7efcb2b750068cee0cf565ee582a35eac990c14c2ca647d9d8cc314d4f5
7
+ data.tar.gz: b813c1b1acd0b1cf0680bf0ecae7eef33b6eb576ff5735d76f072e82fc5cfb36e80ec5b0a3fde6829ec3de856e903b42164a917b833019c33a11d79d6db6080b
@@ -1,17 +1,26 @@
1
1
  name: ci
2
2
  on: [push, pull_request]
3
3
  jobs:
4
- ruby:
4
+ test:
5
5
  strategy:
6
+ fail-fast: false
6
7
  matrix:
7
- ruby: [2.5.x, 2.6.x, 2.7.x]
8
- runs-on: ubuntu-latest
8
+ os: [ubuntu-latest, windows-latest, macos-latest]
9
+ ruby: [2.4, 2.5, 2.6, 2.7, 3.0, head, jruby, jruby-head, truffleruby, truffleruby-head]
10
+ exclude:
11
+ - os: windows-latest
12
+ ruby: jruby
13
+ - os: windows-latest
14
+ ruby: jruby-head
15
+ - os: windows-latest
16
+ ruby: truffleruby
17
+ - os: windows-latest
18
+ ruby: truffleruby-head
19
+ runs-on: ${{ matrix.os }}
9
20
  steps:
10
- - uses: actions/checkout@v1
11
- - uses: actions/setup-ruby@v1
21
+ - uses: actions/checkout@v2
22
+ - uses: ruby/setup-ruby@v1
12
23
  with:
13
24
  ruby-version: ${{ matrix.ruby }}
14
- - run: |
15
- gem install bundler
16
- bundle install
17
- bundle exec rake test
25
+ bundler-cache: true
26
+ - run: bundle exec rake test
data/Gemfile.lock CHANGED
@@ -1,21 +1,21 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json_schemer (0.2.13)
5
- ecma-re-validator (~> 0.2)
4
+ json_schemer (0.2.18)
5
+ ecma-re-validator (~> 0.3)
6
6
  hana (~> 1.3)
7
- regexp_parser (~> 1.5)
7
+ regexp_parser (~> 2.0)
8
8
  uri_template (~> 0.7)
9
9
 
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- ecma-re-validator (0.2.1)
14
- regexp_parser (~> 1.2)
15
- hana (1.3.6)
16
- minitest (5.11.3)
13
+ ecma-re-validator (0.3.0)
14
+ regexp_parser (~> 2.0)
15
+ hana (1.3.7)
16
+ minitest (5.14.3)
17
17
  rake (13.0.1)
18
- regexp_parser (1.7.1)
18
+ regexp_parser (2.1.1)
19
19
  uri_template (0.7.0)
20
20
 
21
21
  PLATFORMS
@@ -28,4 +28,4 @@ DEPENDENCIES
28
28
  rake (~> 13.0)
29
29
 
30
30
  BUNDLED WITH
31
- 2.1.4
31
+ 2.2.11
data/README.md CHANGED
@@ -92,6 +92,20 @@ JSONSchemer.schema(
92
92
  # default: false
93
93
  insert_property_defaults: true,
94
94
 
95
+ # modify properties during validation. You can pass one Proc or a list of Procs to modify data.
96
+ # Proc/[Proc]
97
+ # default: nil
98
+ before_property_validation: proc do |data, property, property_schema, _parent|
99
+ data[property] ||= 42
100
+ end,
101
+
102
+ # modify properties after validation. You can pass one Proc or a list of Procs to modify data.
103
+ # Proc/[Proc]
104
+ # default: nil
105
+ after_property_validation: proc do |data, property, property_schema, _parent|
106
+ data[property] = Date.iso8601(data[property]) if property_schema.is_a?(Hash) && property_schema['format'] == 'date'
107
+ end,
108
+
95
109
  # resolve external references
96
110
  # 'net/http'/proc/lambda/respond_to?(:call)
97
111
  # 'net/http': proc { |uri| JSON.parse(Net::HTTP.get(uri)) }
data/json_schemer.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
- spec.required_ruby_version = '~> 2.5'
23
+ spec.required_ruby_version = '>= 2.4'
24
24
 
25
25
  spec.add_development_dependency "bundler", "~> 2.0"
26
26
  spec.add_development_dependency "rake", "~> 13.0"
@@ -34,8 +34,8 @@ Gem::Specification.new do |spec|
34
34
  # spec.add_development_dependency "jsonschema", "~> 2.0.2"
35
35
  # spec.add_development_dependency "rj_schema", "~> 0.2.0"
36
36
 
37
- spec.add_runtime_dependency "ecma-re-validator", "~> 0.2"
37
+ spec.add_runtime_dependency "ecma-re-validator", "~> 0.3"
38
38
  spec.add_runtime_dependency "hana", "~> 1.3"
39
39
  spec.add_runtime_dependency "uri_template", "~> 0.7"
40
- spec.add_runtime_dependency "regexp_parser", "~> 1.5"
40
+ spec.add_runtime_dependency "regexp_parser", "~> 2.0"
41
41
  end
data/lib/json_schemer.rb CHANGED
@@ -37,10 +37,14 @@ module JSONSchemer
37
37
 
38
38
  DEFAULT_META_SCHEMA = 'http://json-schema.org/draft-07/schema#'
39
39
 
40
+ WINDOWS_URI_PATH_REGEX = /\A\/[a-z]:/i
41
+
40
42
  FILE_URI_REF_RESOLVER = proc do |uri|
41
43
  raise InvalidFileURI, 'must use `file` scheme' unless uri.scheme == 'file'
42
44
  raise InvalidFileURI, 'cannot have a host (use `file:///`)' if uri.host && !uri.host.empty?
43
- JSON.parse(File.read(uri.path))
45
+ path = uri.path
46
+ path = path[1..-1] if path.match?(WINDOWS_URI_PATH_REGEX)
47
+ JSON.parse(File.read(path))
44
48
  end
45
49
 
46
50
  class << self
@@ -49,7 +53,7 @@ module JSONSchemer
49
53
  when String
50
54
  schema = JSON.parse(schema)
51
55
  when Pathname
52
- uri = URI.parse("file://#{schema.realpath}")
56
+ uri = URI.parse(File.join('file:', schema.realpath))
53
57
  if options.key?(:ref_resolver)
54
58
  schema = FILE_URI_REF_RESOLVER.call(uri)
55
59
  else
@@ -3,7 +3,7 @@ module JSONSchemer
3
3
  module Format
4
4
  # this is no good
5
5
  EMAIL_REGEX = /\A[^@\s]+@([\p{L}\d-]+\.)+[\p{L}\d\-]{2,}\z/i.freeze
6
- LABEL_REGEX_STRING = '\p{L}([\p{L}\p{N}\-]*[\p{L}\p{N}])?'
6
+ LABEL_REGEX_STRING = '[\p{L}\p{N}]([\p{L}\p{N}\-]*[\p{L}\p{N}])?'
7
7
  HOSTNAME_REGEX = /\A(#{LABEL_REGEX_STRING}\.)*#{LABEL_REGEX_STRING}\z/i.freeze
8
8
  JSON_POINTER_REGEX_STRING = '(\/([^~\/]|~[01])*)*'
9
9
  JSON_POINTER_REGEX = /\A#{JSON_POINTER_REGEX_STRING}\z/.freeze
@@ -61,7 +61,6 @@ module JSONSchemer
61
61
  DateTime.rfc3339(data)
62
62
  DATE_TIME_OFFSET_REGEX.match?(data)
63
63
  rescue ArgumentError => e
64
- raise e unless e.message == 'invalid date'
65
64
  false
66
65
  end
67
66
 
@@ -101,7 +100,14 @@ module JSONSchemer
101
100
  end
102
101
 
103
102
  def iri_escape(data)
104
- URI.escape(data, /[^[[:ascii:]]]/)
103
+ data.gsub(/[^[:ascii:]]/) do |match|
104
+ us = match
105
+ tmp = +''
106
+ us.each_byte do |uc|
107
+ tmp << sprintf('%%%02X', uc)
108
+ end
109
+ tmp
110
+ end.force_encoding(Encoding::US_ASCII)
105
111
  end
106
112
 
107
113
  def valid_uri_template?(data)
@@ -4,16 +4,17 @@ module JSONSchemer
4
4
  class Base
5
5
  include Format
6
6
 
7
- Instance = Struct.new(:data, :data_pointer, :schema, :schema_pointer, :parent_uri, :insert_property_defaults) do
7
+ Instance = Struct.new(:data, :data_pointer, :schema, :schema_pointer, :parent_uri, :before_property_validation, :after_property_validation) do
8
8
  def merge(
9
9
  data: self.data,
10
10
  data_pointer: self.data_pointer,
11
11
  schema: self.schema,
12
12
  schema_pointer: self.schema_pointer,
13
13
  parent_uri: self.parent_uri,
14
- insert_property_defaults: self.insert_property_defaults
14
+ before_property_validation: self.before_property_validation,
15
+ after_property_validation: self.after_property_validation
15
16
  )
16
- self.class.new(data, data_pointer, schema, schema_pointer, parent_uri, insert_property_defaults)
17
+ self.class.new(data, data_pointer, schema, schema_pointer, parent_uri, before_property_validation, after_property_validation)
17
18
  end
18
19
  end
19
20
 
@@ -29,10 +30,18 @@ module JSONSchemer
29
30
  :eol => '\z'
30
31
  }.freeze
31
32
 
33
+ INSERT_DEFAULT_PROPERTY = proc do |data, property, property_schema, _parent|
34
+ if !data.key?(property) && property_schema.is_a?(Hash) && property_schema.key?('default')
35
+ data[property] = property_schema.fetch('default').clone
36
+ end
37
+ end
38
+
32
39
  def initialize(
33
40
  schema,
34
41
  format: true,
35
42
  insert_property_defaults: false,
43
+ before_property_validation: nil,
44
+ after_property_validation: nil,
36
45
  formats: nil,
37
46
  keywords: nil,
38
47
  ref_resolver: DEFAULT_REF_RESOLVER
@@ -40,18 +49,20 @@ module JSONSchemer
40
49
  raise InvalidSymbolKey, 'schemas must use string keys' if schema.is_a?(Hash) && !schema.empty? && !schema.first.first.is_a?(String)
41
50
  @root = schema
42
51
  @format = format
43
- @insert_property_defaults = insert_property_defaults
52
+ @before_property_validation = [*before_property_validation]
53
+ @before_property_validation.unshift(INSERT_DEFAULT_PROPERTY) if insert_property_defaults
54
+ @after_property_validation = [*after_property_validation]
44
55
  @formats = formats
45
56
  @keywords = keywords
46
57
  @ref_resolver = ref_resolver == 'net/http' ? CachedRefResolver.new(&NET_HTTP_REF_RESOLVER) : ref_resolver
47
58
  end
48
59
 
49
60
  def valid?(data)
50
- valid_instance?(Instance.new(data, '', root, '', nil, !!@insert_property_defaults))
61
+ valid_instance?(Instance.new(data, '', root, '', nil, @before_property_validation, @after_property_validation))
51
62
  end
52
63
 
53
64
  def validate(data)
54
- validate_instance(Instance.new(data, '', root, '', nil, !!@insert_property_defaults))
65
+ validate_instance(Instance.new(data, '', root, '', nil, @before_property_validation, @after_property_validation))
55
66
  end
56
67
 
57
68
  protected
@@ -101,7 +112,7 @@ module JSONSchemer
101
112
  if keywords
102
113
  keywords.each do |keyword, callable|
103
114
  if schema.key?(keyword)
104
- result = callable.call(data, schema, instance.pointer)
115
+ result = callable.call(data, schema, instance.data_pointer)
105
116
  if result.is_a?(Array)
106
117
  result.each(&block)
107
118
  elsif !result
@@ -119,7 +130,8 @@ module JSONSchemer
119
130
  subinstance = instance.merge(
120
131
  schema: subschema,
121
132
  schema_pointer: "#{instance.schema_pointer}/allOf/#{index}",
122
- insert_property_defaults: false
133
+ before_property_validation: false,
134
+ after_property_validation: false
123
135
  )
124
136
  validate_instance(subinstance, &block)
125
137
  end
@@ -130,7 +142,8 @@ module JSONSchemer
130
142
  subinstance = instance.merge(
131
143
  schema: subschema,
132
144
  schema_pointer: "#{instance.schema_pointer}/anyOf/#{index}",
133
- insert_property_defaults: false
145
+ before_property_validation: false,
146
+ after_property_validation: false
134
147
  )
135
148
  validate_instance(subinstance)
136
149
  end
@@ -142,7 +155,8 @@ module JSONSchemer
142
155
  subinstance = instance.merge(
143
156
  schema: subschema,
144
157
  schema_pointer: "#{instance.schema_pointer}/oneOf/#{index}",
145
- insert_property_defaults: false
158
+ before_property_validation: false,
159
+ after_property_validation: false
146
160
  )
147
161
  validate_instance(subinstance)
148
162
  end
@@ -158,12 +172,13 @@ module JSONSchemer
158
172
  subinstance = instance.merge(
159
173
  schema: not_schema,
160
174
  schema_pointer: "#{instance.schema_pointer}/not",
161
- insert_property_defaults: false
175
+ before_property_validation: false,
176
+ after_property_validation: false
162
177
  )
163
178
  yield error(subinstance, 'not') if valid_instance?(subinstance)
164
179
  end
165
180
 
166
- if if_schema && valid_instance?(instance.merge(schema: if_schema, insert_property_defaults: false))
181
+ if if_schema && valid_instance?(instance.merge(schema: if_schema, before_property_validation: false, after_property_validation: false))
167
182
  validate_instance(instance.merge(schema: then_schema, schema_pointer: "#{instance.schema_pointer}/then"), &block) unless then_schema.nil?
168
183
  elsif if_schema
169
184
  validate_instance(instance.merge(schema: else_schema, schema_pointer: "#{instance.schema_pointer}/else"), &block) unless else_schema.nil?
@@ -487,10 +502,10 @@ module JSONSchemer
487
502
  dependencies = schema['dependencies']
488
503
  property_names = schema['propertyNames']
489
504
 
490
- if instance.insert_property_defaults && properties
505
+ if instance.before_property_validation && properties
491
506
  properties.each do |property, property_schema|
492
- if !data.key?(property) && property_schema.is_a?(Hash) && property_schema.key?('default')
493
- data[property] = property_schema.fetch('default').clone
507
+ instance.before_property_validation.each do |hook|
508
+ hook.call(data, property, property_schema, schema)
494
509
  end
495
510
  end
496
511
  end
@@ -565,15 +580,21 @@ module JSONSchemer
565
580
  validate_instance(subinstance, &block)
566
581
  end
567
582
  end
583
+
584
+ if instance.after_property_validation && properties
585
+ properties.each do |property, property_schema|
586
+ instance.after_property_validation.each do |hook|
587
+ hook.call(data, property, property_schema, schema)
588
+ end
589
+ end
590
+ end
568
591
  end
569
592
 
570
593
  def safe_strict_decode64(data)
571
- begin
572
- Base64.strict_decode64(data)
573
- rescue ArgumentError => e
574
- raise e unless e.message == 'invalid base64'
575
- nil
576
- end
594
+ Base64.strict_decode64(data)
595
+ rescue ArgumentError => e
596
+ raise e unless e.message == 'invalid base64'
597
+ nil
577
598
  end
578
599
 
579
600
  def ecma_262_regex(pattern)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module JSONSchemer
3
- VERSION = '0.2.13'
3
+ VERSION = '0.2.18'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_schemer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.13
4
+ version: 0.2.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Harsha
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-08 00:00:00.000000000 Z
11
+ date: 2021-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.2'
61
+ version: '0.3'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.2'
68
+ version: '0.3'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: hana
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '1.5'
103
+ version: '2.0'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '1.5'
110
+ version: '2.0'
111
111
  description:
112
112
  email:
113
113
  - davishmcclurg@gmail.com
@@ -144,17 +144,16 @@ require_paths:
144
144
  - lib
145
145
  required_ruby_version: !ruby/object:Gem::Requirement
146
146
  requirements:
147
- - - "~>"
147
+ - - ">="
148
148
  - !ruby/object:Gem::Version
149
- version: '2.5'
149
+ version: '2.4'
150
150
  required_rubygems_version: !ruby/object:Gem::Requirement
151
151
  requirements:
152
152
  - - ">="
153
153
  - !ruby/object:Gem::Version
154
154
  version: '0'
155
155
  requirements: []
156
- rubyforge_project:
157
- rubygems_version: 2.7.6
156
+ rubygems_version: 3.1.4
158
157
  signing_key:
159
158
  specification_version: 4
160
159
  summary: JSON Schema validator. Supports drafts 4, 6, and 7.