json_model_rb 0.1.19 → 0.1.22

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +156 -572
  3. data/lib/json_model/builder/alias_builder.rb +10 -0
  4. data/lib/json_model/builder/array_builder.rb +24 -0
  5. data/lib/json_model/builder/base_builder.rb +24 -0
  6. data/lib/json_model/builder/composition/any_of_builder.rb +16 -0
  7. data/lib/json_model/builder/composition/builder.rb +47 -0
  8. data/lib/json_model/builder/composition/intersection_builder.rb +16 -0
  9. data/lib/json_model/builder/composition/one_of_builder.rb +16 -0
  10. data/lib/json_model/builder/composition/sum_builder.rb +16 -0
  11. data/lib/json_model/builder/composition.rb +6 -0
  12. data/lib/json_model/builder/constrained_builder.rb +83 -0
  13. data/lib/json_model/builder/default_builder.rb +14 -0
  14. data/lib/json_model/builder/enum_builder.rb +16 -0
  15. data/lib/json_model/builder/format_builder.rb +47 -0
  16. data/lib/json_model/builder/key_builder.rb +30 -0
  17. data/lib/json_model/builder/nested_builder.rb +31 -0
  18. data/lib/json_model/builder/primitive/boolean_builder.rb +16 -0
  19. data/lib/json_model/builder/primitive/builder.rb +25 -0
  20. data/lib/json_model/builder/primitive/integer_builder.rb +16 -0
  21. data/lib/json_model/builder/primitive/null_builder.rb +16 -0
  22. data/lib/json_model/builder/primitive/number_builder.rb +16 -0
  23. data/lib/json_model/builder/primitive/string_builder.rb +16 -0
  24. data/lib/json_model/builder/primitive.rb +7 -0
  25. data/lib/json_model/builder/ref_builder.rb +35 -0
  26. data/lib/json_model/builder/schema_builder.rb +14 -0
  27. data/lib/json_model/builder.rb +65 -0
  28. data/lib/json_model/config/options.rb +5 -2
  29. data/lib/json_model/config.rb +0 -2
  30. data/lib/json_model/errors.rb +0 -3
  31. data/lib/json_model/logic/predicates/methods.rb +17 -0
  32. data/lib/json_model/predicates.rb +3 -0
  33. data/lib/json_model/schema.rb +41 -77
  34. data/lib/json_model/schema_meta.rb +7 -28
  35. data/lib/json_model/types/alias.rb +33 -0
  36. data/lib/json_model/types/any_of.rb +51 -20
  37. data/lib/json_model/types/one_of.rb +51 -20
  38. data/lib/json_model/types/ref.rb +32 -0
  39. data/lib/json_model/types.rb +47 -9
  40. data/lib/json_model/version.rb +1 -1
  41. data/lib/json_model.rb +3 -6
  42. data/spec/config_spec.rb +0 -14
  43. data/spec/examples/file_system_spec.rb +71 -31
  44. data/spec/examples/user_spec.rb +67 -26
  45. data/spec/schema_meta_spec.rb +0 -40
  46. data/spec/schema_spec.rb +43 -59
  47. metadata +84 -57
  48. data/lib/json_model/errors/invalid_ref_mode_error.rb +0 -12
  49. data/lib/json_model/errors/type_error.rb +0 -8
  50. data/lib/json_model/errors/unknown_attribute_error.rb +0 -13
  51. data/lib/json_model/properties.rb +0 -86
  52. data/lib/json_model/property.rb +0 -54
  53. data/lib/json_model/ref_mode.rb +0 -9
  54. data/lib/json_model/type_spec/array.rb +0 -72
  55. data/lib/json_model/type_spec/castable.rb +0 -34
  56. data/lib/json_model/type_spec/composition/all_of.rb +0 -29
  57. data/lib/json_model/type_spec/composition/any_of.rb +0 -34
  58. data/lib/json_model/type_spec/composition/one_of.rb +0 -38
  59. data/lib/json_model/type_spec/composition.rb +0 -79
  60. data/lib/json_model/type_spec/const.rb +0 -35
  61. data/lib/json_model/type_spec/enum.rb +0 -35
  62. data/lib/json_model/type_spec/object.rb +0 -32
  63. data/lib/json_model/type_spec/primitive/boolean.rb +0 -13
  64. data/lib/json_model/type_spec/primitive/integer.rb +0 -21
  65. data/lib/json_model/type_spec/primitive/null.rb +0 -13
  66. data/lib/json_model/type_spec/primitive/number.rb +0 -14
  67. data/lib/json_model/type_spec/primitive/numeric.rb +0 -85
  68. data/lib/json_model/type_spec/primitive/string.rb +0 -150
  69. data/lib/json_model/type_spec/primitive.rb +0 -40
  70. data/lib/json_model/type_spec.rb +0 -82
  71. data/lib/json_model/types/all_of.rb +0 -29
  72. data/lib/json_model/types/array.rb +0 -29
  73. data/lib/json_model/types/boolean.rb +0 -7
  74. data/lib/json_model/types/const.rb +0 -23
  75. data/lib/json_model/types/enum.rb +0 -23
  76. data/lib/json_model/types/integer.rb +0 -23
  77. data/lib/json_model/types/null.rb +0 -7
  78. data/lib/json_model/types/number.rb +0 -23
  79. data/lib/json_model/types/string.rb +0 -23
  80. data/spec/properties_spec.rb +0 -76
  81. data/spec/property_spec.rb +0 -86
  82. data/spec/type_spec/array_spec.rb +0 -206
  83. data/spec/type_spec/castable_spec.rb +0 -19
  84. data/spec/type_spec/composition/all_of_spec.rb +0 -57
  85. data/spec/type_spec/composition/any_of_spec.rb +0 -54
  86. data/spec/type_spec/composition/one_of_spec.rb +0 -59
  87. data/spec/type_spec/composition_spec.rb +0 -90
  88. data/spec/type_spec/const_spec.rb +0 -18
  89. data/spec/type_spec/enum_spec.rb +0 -84
  90. data/spec/type_spec/primitive/boolean_spec.rb +0 -12
  91. data/spec/type_spec/primitive/integer_spec.rb +0 -57
  92. data/spec/type_spec/primitive/null_spec.rb +0 -12
  93. data/spec/type_spec/primitive/number_spec.rb +0 -12
  94. data/spec/type_spec/primitive/numeric_spec.rb +0 -176
  95. data/spec/type_spec/primitive/string_spec.rb +0 -119
  96. data/spec/type_spec_spec.rb +0 -32
@@ -6,62 +6,87 @@ RSpec.describe('File system schema') do
6
6
  before do
7
7
  stub_const(
8
8
  'DiskDevice',
9
- Class.new do
9
+ Class.new(Dry::Struct) do
10
10
  include(JsonModel::Schema)
11
11
 
12
- property(:type, type: T::Const['disk'])
13
- property(:device, type: T::String[pattern: %r{\A/dev/[^/]+(/[^/]+)*\z}])
12
+ def self.name
13
+ 'DiskDevice'
14
+ end
15
+
16
+ attribute(:type, JsonModel::Types::String.constrained(eql: 'disk'))
17
+ attribute(:device, JsonModel::Types::String.constrained(format: %r{\A/dev/[^/]+(/[^/]+)*\z}))
14
18
  end,
15
19
  )
16
20
 
17
21
  stub_const(
18
22
  'DiskUuid',
19
- Class.new do
23
+ Class.new(Dry::Struct) do
20
24
  include(JsonModel::Schema)
21
25
 
22
- property(:type, type: T::Enum['diskUUID', 'diskuuid'])
23
- property(
26
+ def self.name
27
+ 'DiskUuid'
28
+ end
29
+
30
+ attribute(:type, JsonModel::Types::String.enum('diskUUID', 'diskuuid'))
31
+ attribute(
24
32
  :label,
25
- type: T::String[pattern: /\A[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\z/],
33
+ JsonModel::Types::String.constrained(
34
+ format: /\A[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\z/,
35
+ ),
26
36
  )
27
37
  end,
28
38
  )
29
39
 
30
40
  stub_const(
31
41
  'Nfs',
32
- Class.new do
42
+ Class.new(Dry::Struct) do
33
43
  include(JsonModel::Schema)
34
44
 
35
- property(:type, type: T::Const['nfs'])
36
- property(:remote_path, type: T::String[pattern: %r{\A(/[^/]+)+\z}], as: :remotePath)
37
- property(:server, type: T::String[format: :ipv4])
45
+ def self.name
46
+ 'Nfs'
47
+ end
48
+
49
+ attribute(:type, JsonModel::Types::String.constrained(eql: 'nfs'))
50
+ attribute(:remote_path, JsonModel::Types::String.constrained(format: %r{\A(/[^/]+)+\z}).as(:remotePath))
51
+ attribute(:server, JsonModel::Types::IPv4)
38
52
  end,
39
53
  )
40
54
 
41
55
  stub_const(
42
56
  'Tmpfs',
43
- Class.new do
57
+ Class.new(Dry::Struct) do
44
58
  include(JsonModel::Schema)
45
59
 
46
- property(:type, type: T::Const['tmpfs'])
47
- property(:size_in_mb, type: T::Integer[minimum: 16, maximum: 512], as: :sizeInMB)
60
+ def self.name
61
+ 'Tmpfs'
62
+ end
63
+
64
+ attribute(:type, JsonModel::Types::String.constrained(eql: 'tmpfs'))
65
+ attribute(:size_in_mb, JsonModel::Types::Integer.constrained(gteq: 16, lteq: 512).as(:sizeInMB))
48
66
  end,
49
67
  )
50
68
 
51
69
  stub_const(
52
70
  'Fstab',
53
- Class.new do
71
+ Class.new(Dry::Struct) do
54
72
  include(JsonModel::Schema)
55
73
 
56
74
  description('JSON Schema for an fstab entry')
57
- property(
75
+ attribute(
58
76
  :storage,
59
- type: T::OneOf[DiskDevice, DiskUuid, Nfs, Tmpfs, discriminator: :type],
60
- ref_mode: JsonModel::RefMode::LOCAL,
77
+ JsonModel::Types.one_of(:type) do
78
+ on('disk', DiskDevice.local)
79
+ on('diskUUID', 'diskuuid', DiskUuid.local)
80
+ on('nfs', Nfs.local)
81
+ on('tmpfs', Tmpfs.local)
82
+ end,
61
83
  )
62
- property(:fstype, type: T::Enum['ext3', 'ext4', 'btrfs'], optional: true)
63
- property(:options, type: T::Array[String, min_items: 1, unique_items: true], optional: true)
64
- property(:readonly, type: T::Boolean, optional: true)
84
+ attribute(:fstype, JsonModel::Types::String.enum('ext3', 'ext4', 'btrfs'))
85
+ attribute(
86
+ :options,
87
+ JsonModel::Types::Array.of(JsonModel::Types::String).constrained(min_size: 1, unique: true).optional,
88
+ )
89
+ attribute?(:readonly, JsonModel::Types::Bool.optional)
65
90
  end,
66
91
  )
67
92
  end
@@ -73,7 +98,7 @@ RSpec.describe('File system schema') do
73
98
  {
74
99
  description: 'JSON Schema for an fstab entry',
75
100
  type: 'object',
76
- required: %i(storage),
101
+ required: %i(fstype storage),
77
102
  properties: {
78
103
  storage: {
79
104
  oneOf: [
@@ -87,15 +112,23 @@ RSpec.describe('File system schema') do
87
112
  enum: %w(ext3 ext4 btrfs),
88
113
  },
89
114
  options: {
90
- type: 'array',
91
- minItems: 1,
92
- items: {
93
- type: 'string',
94
- },
95
- uniqueItems: true,
115
+ anyOf: [
116
+ { type: 'null' },
117
+ {
118
+ type: 'array',
119
+ minItems: 1,
120
+ items: {
121
+ type: 'string',
122
+ },
123
+ uniqueItems: true,
124
+ },
125
+ ],
96
126
  },
97
127
  readonly: {
98
- type: 'boolean',
128
+ anyOf: [
129
+ { type: 'null' },
130
+ { type: 'boolean' },
131
+ ],
99
132
  },
100
133
  },
101
134
  '$defs': {
@@ -103,6 +136,7 @@ RSpec.describe('File system schema') do
103
136
  properties: {
104
137
  type: {
105
138
  const: 'disk',
139
+ type: 'string',
106
140
  },
107
141
  device: {
108
142
  type: 'string',
@@ -125,7 +159,10 @@ RSpec.describe('File system schema') do
125
159
  },
126
160
  Nfs: {
127
161
  properties: {
128
- type: { const: 'nfs' },
162
+ type: {
163
+ const: 'nfs',
164
+ type: 'string',
165
+ },
129
166
  remotePath: {
130
167
  type: 'string',
131
168
  pattern: '\\A(/[^/]+)+\\z',
@@ -140,7 +177,10 @@ RSpec.describe('File system schema') do
140
177
  },
141
178
  Tmpfs: {
142
179
  properties: {
143
- type: { const: 'tmpfs' },
180
+ type: {
181
+ const: 'tmpfs',
182
+ type: 'string',
183
+ },
144
184
  sizeInMB: { type: 'integer', minimum: 16, maximum: 512 },
145
185
  },
146
186
  required: %i(sizeInMB type),
@@ -4,38 +4,38 @@ require('spec_helper')
4
4
 
5
5
  RSpec.describe('User schema') do
6
6
  before do
7
- address_class = Class.new do
7
+ address_class = Class.new(Dry::Struct) do
8
8
  include(JsonModel::Schema)
9
9
 
10
10
  def self.name
11
11
  'Address'
12
12
  end
13
13
 
14
- property(:street, type: String)
15
- property(:city, type: String)
16
- property(:state, type: String, optional: true)
17
- property(:postal_code, type: T::String[pattern: /\A\d{5}(-\d{4})?\z/], optional: true)
18
- property(:country, type: String, default: 'USA')
14
+ attribute(:street, JsonModel::Types::String)
15
+ attribute(:city, JsonModel::Types::String)
16
+ attribute?(:state, JsonModel::Types::String.optional)
17
+ attribute?(:postal_code, JsonModel::Types::String.constrained(format: /\A\d{5}(-\d{4})?\z/).optional)
18
+ attribute(:country, JsonModel::Types::String.default('USA'))
19
19
  end
20
20
 
21
21
  stub_const('Address', address_class)
22
22
 
23
- user_class = Class.new do
23
+ user_class = Class.new(Dry::Struct) do
24
24
  include(JsonModel::Schema)
25
25
 
26
26
  def self.name
27
27
  'User'
28
28
  end
29
29
 
30
- property(:name, type: String)
31
- property(:email, type: T::String[format: :email])
32
- property(:age, type: T::Integer[minimum: 0, maximum: 120], optional: true)
33
- property(:active, type: T::Boolean, default: true, optional: true)
34
- property(:addresses, type: T::Array[Address], ref_mode: JsonModel::RefMode::LOCAL)
35
- property(:tags, type: T::Array[String], optional: true)
36
- property(:birthday, type: Date, optional: true)
37
- property(:websites, type: T::Array[URI], optional: true)
38
- property(:height, type: Float, optional: true)
30
+ attribute(:name, JsonModel::Types::String.constrained(min_size: 3))
31
+ attribute(:email, JsonModel::Types::Email)
32
+ attribute?(:age, JsonModel::Types::Integer.constrained(gteq: 0, lteq: 120).optional)
33
+ attribute(:active, JsonModel::Types::Bool.optional.default(true))
34
+ attribute(:addresses, JsonModel::Types::Array.of(Address.local))
35
+ attribute?(:tags, JsonModel::Types::Array.of(JsonModel::Types::String).optional)
36
+ attribute(:birthday, JsonModel::Types::Date.optional)
37
+ attribute?(:websites, JsonModel::Types::Array.of(JsonModel::Types::URI).optional)
38
+ attribute?(:height, JsonModel::Types::Float.optional)
39
39
  end
40
40
 
41
41
  stub_const('User', user_class)
@@ -48,18 +48,49 @@ RSpec.describe('User schema') do
48
48
  {
49
49
  type: 'object',
50
50
  properties: {
51
- name: { type: 'string' },
51
+ name: { type: 'string', minLength: 3 },
52
52
  email: { type: 'string', format: 'email' },
53
- age: { type: 'integer', minimum: 0, maximum: 120 },
54
- active: { type: 'boolean', default: true },
53
+ age: {
54
+ anyOf: [
55
+ { type: 'null' },
56
+ { type: 'integer', minimum: 0, maximum: 120 },
57
+ ],
58
+ },
59
+ active: {
60
+ anyOf: [
61
+ { type: 'null' },
62
+ { type: 'boolean' },
63
+ ],
64
+ default: true,
65
+ },
55
66
  addresses: {
56
67
  type: 'array',
57
68
  items: { '$ref': '#/$defs/Address' },
58
69
  },
59
- tags: { type: 'array', items: { type: 'string' } },
60
- birthday: { type: 'string', format: 'date' },
61
- websites: { type: 'array', items: { type: 'string', format: 'uri' } },
62
- height: { type: 'number' },
70
+ tags: {
71
+ anyOf: [
72
+ { type: 'null' },
73
+ { type: 'array', items: { type: 'string' } },
74
+ ],
75
+ },
76
+ birthday: {
77
+ anyOf: [
78
+ { type: 'null' },
79
+ { type: 'string', format: 'date' },
80
+ ],
81
+ },
82
+ websites: {
83
+ anyOf: [
84
+ { type: 'null' },
85
+ { type: 'array', items: { type: 'string', format: 'uri' } },
86
+ ],
87
+ },
88
+ height: {
89
+ anyOf: [
90
+ { type: 'null' },
91
+ { type: 'number' },
92
+ ],
93
+ },
63
94
  },
64
95
  required: %i(addresses email name),
65
96
  '$defs': {
@@ -68,8 +99,18 @@ RSpec.describe('User schema') do
68
99
  properties: {
69
100
  city: { type: 'string' },
70
101
  country: { type: 'string', default: 'USA' },
71
- postal_code: { type: 'string', pattern: '\A\d{5}(-\d{4})?\z' },
72
- state: { type: 'string' },
102
+ postal_code: {
103
+ anyOf: [
104
+ { type: 'null' },
105
+ { type: 'string', pattern: '\A\d{5}(-\d{4})?\z' },
106
+ ],
107
+ },
108
+ state: {
109
+ anyOf: [
110
+ { type: 'null' },
111
+ { type: 'string' },
112
+ ],
113
+ },
73
114
  street: { type: 'string' },
74
115
  },
75
116
  required: %i(city country street),
@@ -85,7 +126,7 @@ RSpec.describe('User schema') do
85
126
  name: 'Foo',
86
127
  email: 'foo@example.com',
87
128
  addresses: [{ street: '123 Main St', city: 'Anytown' }],
88
- birthday: '2000-01-01',
129
+ birthday: Date.new(2000, 1, 1),
89
130
  )
90
131
 
91
132
  expect(user.name).to(eq('Foo'))
@@ -95,44 +95,4 @@ RSpec.describe(JsonModel::SchemaMeta) do
95
95
  .to(eq('This is a test title.'))
96
96
  end
97
97
  end
98
-
99
- describe('.additional_properties') do
100
- let(:klass) do
101
- Class.new do
102
- include(JsonModel::SchemaMeta)
103
- end
104
- end
105
-
106
- it('is missing by default') do
107
- expect(klass.meta_attributes)
108
- .to(eq({}))
109
- end
110
-
111
- it('can be changed') do
112
- klass.additional_properties(true)
113
-
114
- expect(klass.meta_attributes)
115
- .to(eq({ additionalProperties: true }))
116
- end
117
- end
118
-
119
- describe('.additional_properties') do
120
- let(:klass) do
121
- Class.new do
122
- include(JsonModel::SchemaMeta)
123
- end
124
- end
125
-
126
- it('is missing by default') do
127
- expect(klass.meta_attributes)
128
- .to(eq({}))
129
- end
130
-
131
- it('can be changed') do
132
- klass.unevaluated_properties(true)
133
-
134
- expect(klass.meta_attributes)
135
- .to(eq({ unevaluatedProperties: true }))
136
- end
137
- end
138
98
  end
data/spec/schema_spec.rb CHANGED
@@ -5,10 +5,10 @@ require('spec_helper')
5
5
  RSpec.describe(JsonModel::Schema) do
6
6
  describe('.initialize') do
7
7
  let(:klass) do
8
- Class.new do
8
+ Class.new(Dry::Struct) do
9
9
  include(JsonModel::Schema)
10
10
 
11
- property(:foo, type: String, optional: true)
11
+ attribute?(:foo, JsonModel::Types::String.optional)
12
12
 
13
13
  def self.name
14
14
  'Foo'
@@ -28,49 +28,25 @@ RSpec.describe(JsonModel::Schema) do
28
28
  end
29
29
 
30
30
  it('raises an error for unknown attributes when additional properties are not allowed') do
31
+ klass.schema(klass.schema.strict)
32
+
31
33
  expect { klass.new(bar: 'baz') }
32
- .to(raise_error(JsonModel::Errors::UnknownAttributeError))
34
+ .to(raise_error(Dry::Struct::Error))
33
35
  end
34
36
 
35
37
  it('does not raise an error for unknown attributes when additional properties are allowed') do
36
- klass.additional_properties(true)
37
-
38
38
  klass.new(bar: 'baz')
39
39
  end
40
40
  end
41
41
 
42
- describe('#valid?') do
43
- let(:klass) do
44
- Class.new do
45
- include(JsonModel::Schema)
46
-
47
- property(:foo, type: T::String[min_length: 3])
48
- end
49
- end
50
-
51
- before do
52
- JsonModel.configure { |config| config.validate_after_instantiation = false }
53
- end
54
-
55
- it('returns false for invalid values') do
56
- expect(klass.new(foo: 'ba').valid?)
57
- .to(be(false))
58
- end
59
-
60
- it('returns true for valid values') do
61
- expect(klass.new(foo: 'bar').valid?)
62
- .to(be(true))
63
- end
64
- end
65
-
66
42
  describe('.from_json') do
67
43
  before do
68
44
  stub_const(
69
45
  'Foo',
70
- Class.new do
46
+ Class.new(Dry::Struct) do
71
47
  include(JsonModel::Schema)
72
48
 
73
- property(:foo_bar, type: String, as: :fooBar)
49
+ attribute(:foo_bar, JsonModel::Types::String.as(:fooBar))
74
50
  end,
75
51
  )
76
52
 
@@ -93,7 +69,7 @@ RSpec.describe(JsonModel::Schema) do
93
69
 
94
70
  describe('.as_schema') do
95
71
  let(:klass) do
96
- Class.new do
72
+ Class.new(Dry::Struct) do
97
73
  include(JsonModel::Schema)
98
74
  end
99
75
  end
@@ -119,11 +95,11 @@ RSpec.describe(JsonModel::Schema) do
119
95
 
120
96
  it('returns properties as schema') do
121
97
  klass.schema_id('https://example.com/schemas/example.json')
122
- klass.property(:foo, type: String)
123
- klass.property(:bar, type: Float, optional: true)
124
- klass.property(:baz, type: T::Enum[1, 'a', nil])
125
- klass.property(:bam, type: T::Array[T::AllOf[String, Float]])
126
- klass.property(:bal, type: klass, ref_mode: JsonModel::RefMode::EXTERNAL, optional: true)
98
+ klass.attribute(:foo, JsonModel::Types::String)
99
+ klass.attribute(:bar, JsonModel::Types::Float.optional)
100
+ klass.attribute(:baz, JsonModel::Types::String.enum(1, 'a', nil))
101
+ klass.attribute(:bam, JsonModel::Types::Array.of(JsonModel::Types::String & JsonModel::Types::Float))
102
+ klass.attribute(:bal, klass.external.optional)
127
103
 
128
104
  expect(klass.as_schema)
129
105
  .to(
@@ -132,14 +108,24 @@ RSpec.describe(JsonModel::Schema) do
132
108
  '$id': 'https://example.com/schemas/example.json',
133
109
  type: 'object',
134
110
  properties: {
135
- bal: { '$ref': 'https://example.com/schemas/example.json' },
111
+ bal: {
112
+ anyOf: [
113
+ { type: 'null' },
114
+ { '$ref': 'https://example.com/schemas/example.json' },
115
+ ],
116
+ },
136
117
  bam: {
137
118
  type: 'array',
138
119
  items: {
139
120
  allOf: [{ type: 'string' }, { type: 'number' }],
140
121
  },
141
122
  },
142
- bar: { type: 'number' },
123
+ bar: {
124
+ anyOf: [
125
+ { type: 'null' },
126
+ { type: 'number' },
127
+ ],
128
+ },
143
129
  baz: { enum: [1, 'a', nil] },
144
130
  foo: { type: 'string' },
145
131
  },
@@ -150,40 +136,38 @@ RSpec.describe(JsonModel::Schema) do
150
136
  end
151
137
 
152
138
  it('collects local references in $defs') do
153
- klass.property(
139
+ klass.attribute(
154
140
  :foo,
155
- type: Class.new do
141
+ Class.new(Dry::Struct) do
156
142
  include(JsonModel::Schema)
157
143
 
158
- property(:foo, type: String)
144
+ attribute(:foo, JsonModel::Types::String)
159
145
  end,
160
146
  )
161
- klass.property(
147
+ klass.attribute(
162
148
  :bam,
163
- type: Class.new do
149
+ Class.new(Dry::Struct) do
164
150
  include(JsonModel::Schema)
165
151
 
166
- property(:bam, type: String)
167
152
  schema_id('https://example.com/schemas/bam.json')
168
- end,
169
- ref_mode: JsonModel::RefMode::EXTERNAL,
153
+ attribute(:bam, JsonModel::Types::String)
154
+ end.external,
170
155
  )
171
- klass.property(
156
+ klass.attribute(
172
157
  :bar,
173
- type: T::Array[
174
- T::Array[
175
- Class.new do
158
+ JsonModel::Types::Array.of(
159
+ JsonModel::Types::Array.of(
160
+ Class.new(Dry::Struct) do
176
161
  include(JsonModel::Schema)
177
162
 
178
- property(:bar, type: String)
163
+ attribute(:bar, JsonModel::Types::String)
179
164
 
180
165
  def self.name
181
166
  'Bar'
182
167
  end
183
- end,
184
- ],
185
- ],
186
- ref_mode: JsonModel::RefMode::LOCAL,
168
+ end.local,
169
+ ),
170
+ ),
187
171
  )
188
172
 
189
173
  expect(klass.as_schema)
@@ -223,20 +207,20 @@ RSpec.describe(JsonModel::Schema) do
223
207
  let(:child) do
224
208
  Class.new(klass) do
225
209
  schema_id('https://example.com/schemas/child.json')
226
- property(:baz, type: String)
210
+ attribute(:baz, JsonModel::Types::String)
227
211
  end
228
212
  end
229
213
  let(:second_child) do
230
214
  Class.new(klass) do
231
215
  schema_id('https://example.com/schemas/second-child.json')
232
216
  title('SecondChild')
233
- property(:bar, type: String)
217
+ attribute(:bar, JsonModel::Types::String)
234
218
  end
235
219
  end
236
220
 
237
221
  it('uses $ref for inherited schemas if they have a schema id') do
238
222
  klass.schema_id('https://example.com/schemas/example.json')
239
- klass.property(:foo, type: String)
223
+ klass.attribute(:foo, JsonModel::Types::String)
240
224
 
241
225
  expect(child.as_schema)
242
226
  .to(