json_model_rb 0.1.13 → 0.1.15

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4f530abe8264be24ec3b62c627bbab78fe3d25ace6bbd03a9360d7bbac688f2
4
- data.tar.gz: e1997308062e1cd0b3af670b381bd461324f0c29e49457534cd1196048f57c47
3
+ metadata.gz: ae63a0cef5ca421b32a3a103aeaaa8c61cfe9a1edd7871567e8c8f5905678f5d
4
+ data.tar.gz: b51047217b904c7194deb9c21bcd66a175ae18779360d68a78db5efa3190d12a
5
5
  SHA512:
6
- metadata.gz: aa7626727be77b8da34aa0775f2c8ba3f1f2e636dfca50b83224e51c92e7d78c70079a2732fb0ee17ded82f295d1d2f0654e274b94ceff224b55c36aa99bff88
7
- data.tar.gz: 8bcd5c1fee253effded868ff5466f00969eebd6e50ae6c5ace3dce2bb5befc6ea6be3730bfd3ca9806bf5380267591df23dc679d97bb2751f227a9ef819669bc
6
+ metadata.gz: 05f4f40b76349054936c5df92514615c3a86ebb9eaa54d5e9105c59dc33d836fc4718f98d1590a34d7569ed86e14a292ee70a2f7e17b241fea337f81074e4d82
7
+ data.tar.gz: b9b97ae062116a998eb894e8a98d486dc8ffa141d2a49c5b4755afe41358b0ff4b8aed7a8283bbe744107980a3206a858b2de6d16deacdbe01102bf5a4aed300
data/README.md CHANGED
@@ -99,7 +99,7 @@ class Product
99
99
  # Properties
100
100
  property :id, type: String
101
101
  property :name, type: String
102
- property :price, type: Float, minimum: 0
102
+ property :price, type: T::Float[minimum: 0]
103
103
  property :available, type: T::Boolean, default: true, optional: true
104
104
  end
105
105
  ```
@@ -124,30 +124,28 @@ class StringExample
124
124
  property :simple_string, type: String
125
125
 
126
126
  # String with length constraints
127
- property :username, type: String,
128
- min_length: 3,
129
- max_length: 20
127
+ property :username, type: T::String[min_length: 3, max_length: 20]
130
128
 
131
129
  # String with pattern (regex)
132
- property :product_code, type: String, pattern: /\A[A-Z]{3}-\d{4}\z/
130
+ property :product_code, type: T::String[pattern: /\A[A-Z]{3}-\d{4}\z/]
133
131
 
134
132
  # String with format
135
- property :email, type: String, format: :email
136
- property :uri, type: String, format: :uri
137
- property :hostname, type: String, format: :hostname
138
- property :ipv4, type: String, format: :ipv4
139
- property :ipv6, type: String, format: :ipv6
140
- property :uuid, type: String, format: :uuid
141
- property :date, type: String, format: :date
142
- property :time, type: String, format: :time
143
- property :datetime, type: String, format: :date_time
144
- property :duration, type: String, format: :duration
133
+ property :email, type: T::String[format: :email]
134
+ property :uri, type: T::String[format: :uri]
135
+ property :hostname, type: T::String[format: :hostname]
136
+ property :ipv4, type: T::String[format: :ipv4]
137
+ property :ipv6, type: T::String[format: :ipv6]
138
+ property :uuid, type: T::String[format: :uuid]
139
+ property :date, type: T::String[format: :date]
140
+ property :time, type: T::String[format: :time]
141
+ property :datetime, type: T::String[format: :date_time]
142
+ property :duration, type: T::String[format: :duration]
145
143
 
146
144
  # String with enum
147
- property :status, type: String, enum: ["draft", "published", "archived"]
145
+ property :status, T::Enum["draft", "published", "archived"]
148
146
 
149
147
  # String with const
150
- property :api_version, type: String, const: "v1"
148
+ property :api_version, T::Const["v1"]
151
149
 
152
150
  # Optional string
153
151
  property :nickname, type: String, optional: true
@@ -244,19 +242,19 @@ class NumericExample
244
242
  property :count, type: Integer
245
243
 
246
244
  # Integer with range
247
- property :port, type: Integer, minimum: 1024, maximum: 65535
245
+ property :port, type: T::Integer[minimum: 1024, maximum: 65535]
248
246
 
249
247
  # Integer with exclusive bounds
250
- property :positive_int, type: Integer, exclusive_minimum: 0
248
+ property :positive_int, type: T::Integer[exclusive_minimum: 0]
251
249
 
252
250
  # Number (float/double)
253
- property :price, type: Float, minimum: 0
251
+ property :price, type: T::Number[minimum: 0]
254
252
 
255
253
  # Number with multiple_of
256
- property :quantity, type: Integer, multiple_of: 10
254
+ property :quantity, type: T::Integer[multiple_of: 10]
257
255
 
258
256
  # Number with precision
259
- property :temperature, type: Float, minimum: -273.15, maximum: 1000.0
257
+ property :temperature, type: T::Number[minimum: -273.15, maximum: 1000.0]
260
258
 
261
259
  # Optional number
262
260
  property :discount, type: Float, optional: true
@@ -361,7 +359,7 @@ class ArrayExample
361
359
  property :tags, type: T::Array[String]
362
360
 
363
361
  # Array with constraints
364
- property :numbers, type: T::Array[Integer], min_items: 1, max_items: 10, unique_items: true
362
+ property :numbers, type: T::Array[Integer, min_items: 1, max_items: 10, unique_items: true]
365
363
  end
366
364
 
367
365
  # Generate the JSON Schema
@@ -410,15 +408,15 @@ class PersonBase
410
408
  include JsonModel::Schema
411
409
 
412
410
  property :name, type: String
413
- property :age, type: Integer, minimum: 0, optional: true
411
+ property :age, type: T::Integer[minimum: 0], optional: true
414
412
  end
415
413
 
416
414
  class EmployeeDetails
417
415
  include JsonModel::Schema
418
416
 
419
- property :employee_id, type: String, pattern: /\AE-\d{4}\z/
417
+ property :employee_id, type: T::String[pattern: /\AE-\d{4}\z/]
420
418
  property :department, type: String
421
- property :salary, type: Float, minimum: 0, optional: true
419
+ property :salary, type: T::Number[minimum: 0], optional: true
422
420
  end
423
421
 
424
422
  class Employee
@@ -504,7 +502,7 @@ end
504
502
  class PhoneContact
505
503
  include JsonModel::Schema
506
504
 
507
- property :phone, type: String, pattern: /\A\+?[1-9]\\d{1,14}\z/
505
+ property :phone, type: T::String[pattern: /\A\+?[1-9]\\d{1,14}\z/]
508
506
  end
509
507
 
510
508
  class AddressContact
@@ -596,24 +594,24 @@ Use `T::OneOf` when a value must validate against exactly one schema (exclusive
596
594
  class CreditCardPayment
597
595
  include JsonModel::Schema
598
596
 
599
- property :payment_type, type: String, const: "credit_card"
600
- property :card_number, type: String, pattern: /\A\d{16}\z/
601
- property :cvv, type: String, pattern: /\A\d{3,4}\z/
602
- property :expiry, type: String, pattern: /\A\d{2}\/\d{2}\z/
597
+ property :payment_type, T::Const["credit_card"]
598
+ property :card_number, type: T::String[pattern: /\A\d{16}\z/]
599
+ property :cvv, type: T::String[pattern: /\A\d{3,4}\z/]
600
+ property :expiry, type: T::String[pattern: /\A\d{2}\/\d{2}\z/]
603
601
  end
604
602
 
605
603
  class PayPalPayment
606
604
  include JsonModel::Schema
607
605
 
608
- property :payment_type, type: String, const: "paypal"
609
- property :paypal_email, type: String, format: :email
606
+ property :payment_type, T::Const["paypal"]
607
+ property :paypal_email, type: T::String[format: :email]
610
608
  end
611
609
 
612
610
  class BankTransferPayment
613
611
  include JsonModel::Schema
614
612
 
615
- property :payment_type, type: String, const: "bank_transfer"
616
- property :iban, type: String, pattern: "^[A-Z]{2}\\d{2}[A-Z0-9]+$"
613
+ property :payment_type, type: T::Const["bank_transfer"]
614
+ property :iban, type: T::String[pattern: "^[A-Z]{2}\\d{2}[A-Z0-9]+$"]
617
615
  property :swift, type: String, optional: true
618
616
  end
619
617
 
@@ -623,7 +621,7 @@ class PaymentMethod
623
621
  title "Payment Method"
624
622
  description "Must specify exactly one payment method"
625
623
 
626
- property :payment, type: T::OneOf[CreditCardPayment, PayPalPayment, BankTransferPayment]
624
+ property :payment, type: T::OneOf[CreditCardPayment, PayPalPayment, BankTransferPayment], discriminator: :payment_type
627
625
  end
628
626
 
629
627
  # Generate the JSON Schema
@@ -30,16 +30,16 @@ module JsonModel
30
30
  def invert_alias(name)
31
31
  aliased_properties[name]&.name || superclass&.invert_alias(name)
32
32
  rescue NoMethodError
33
+ nil
33
34
  end
34
35
 
35
36
  # @param [Symbol] name
36
37
  # @param [Object, Class] type
37
38
  # @param [Hash] options
38
39
  def property(name, type:, **options)
39
- property_options = options.slice(:default, :optional, :ref_mode, :as)
40
- resolved_type = TypeSpec.resolve(type, **options.except(:default, :optional, :ref_mode, :as))
41
- add_property(name, type: resolved_type, **property_options)
42
- descendants.each { |subclass| subclass.add_property(name, type: resolved_type, **property_options) }
40
+ resolved_type = TypeSpec.resolve(type)
41
+ add_property(name, type: resolved_type, **options)
42
+ descendants.each { |subclass| subclass.add_property(name, type: resolved_type, **options) }
43
43
  end
44
44
 
45
45
  protected
@@ -17,7 +17,7 @@ module JsonModel
17
17
  return nil
18
18
  end
19
19
 
20
- @types.map do |type|
20
+ types_for(json).map do |type|
21
21
  type.cast(json)
22
22
  rescue StandardError
23
23
  raise(Errors::TypeError, "Value #{json.inspect} cannot be cast to allOf type #{self}")
@@ -17,7 +17,7 @@ module JsonModel
17
17
  return nil
18
18
  end
19
19
 
20
- type = @types.detect do |type|
20
+ type = types_for(json).detect do |type|
21
21
  type.cast(json)
22
22
  rescue StandardError
23
23
  false
@@ -17,7 +17,7 @@ module JsonModel
17
17
  return nil
18
18
  end
19
19
 
20
- types = @types.select do |type|
20
+ types = types_for(json).select do |type|
21
21
  type.cast(json)
22
22
  rescue StandardError
23
23
  false
@@ -3,25 +3,28 @@
3
3
  module JsonModel
4
4
  class TypeSpec
5
5
  class Composition < TypeSpec
6
+ attr_reader(:types, :modifier, :discriminator)
7
+
6
8
  # @param [Symbol] modifier
7
- # @param [TypeSpec] types
8
- def initialize(modifier, *types)
9
+ # @param [::Array<TypeSpec>] types
10
+ def initialize(modifier, *types, discriminator: nil)
9
11
  super()
10
12
  @types = types
11
13
  @modifier = modifier
14
+ @discriminator = discriminator
12
15
  end
13
16
 
14
17
  # @param [Hash] options
15
18
  # @return [Hash]
16
19
  def as_schema(**options)
17
20
  {
18
- @modifier => @types.map { |type| type.as_schema(**options) },
21
+ modifier => types.map { |type| type.as_schema(**options) },
19
22
  }
20
23
  end
21
24
 
22
25
  # @return [Array<TypeSpec>]
23
26
  def referenced_schemas
24
- @types.flat_map(&:referenced_schemas)
27
+ types.flat_map(&:referenced_schemas)
25
28
  end
26
29
 
27
30
  # @param [::Object] json
@@ -29,6 +32,44 @@ module JsonModel
29
32
  def cast(json)
30
33
  raise(NotImplementedError)
31
34
  end
35
+
36
+ protected
37
+
38
+ # @return [Hash, nil]
39
+ def type_map
40
+ if discriminator.nil?
41
+ return nil
42
+ end
43
+
44
+ @type_map ||= types.each_with_object({}) do |type, hash|
45
+ if !type.is_a?(Object)
46
+ raise('Discriminator property can only be used with Object types')
47
+ end
48
+
49
+ discriminator_property = type.type.properties[discriminator]
50
+ discriminator_values = if discriminator_property&.type.is_a?(Const)
51
+ [discriminator_property.type.value]
52
+ elsif discriminator_property&.type.is_a?(Enum)
53
+ discriminator_property.type.values
54
+ else
55
+ raise('Discriminator property must be of type Const or Enum')
56
+ end
57
+ discriminator_values.each do |value|
58
+ hash[value] ||= []
59
+ hash[value] << type
60
+ end
61
+ end
62
+ end
63
+
64
+ # @param [::Object] json
65
+ # @return [::Array<TypeSpec>]
66
+ def types_for(json)
67
+ if type_map.nil?
68
+ types
69
+ else
70
+ type_map[json[discriminator]]
71
+ end
72
+ end
32
73
  end
33
74
  end
34
75
  end
@@ -3,6 +3,8 @@
3
3
  module JsonModel
4
4
  class TypeSpec
5
5
  class Const < TypeSpec
6
+ attr_reader(:value)
7
+
6
8
  # @param [String] value
7
9
  def initialize(value)
8
10
  super()
@@ -17,7 +19,7 @@ module JsonModel
17
19
  # @return [Hash]
18
20
  def as_schema(**_options)
19
21
  {
20
- const: @value,
22
+ const: value,
21
23
  }.compact
22
24
  end
23
25
 
@@ -26,7 +28,7 @@ module JsonModel
26
28
  def register_validations(name, klass)
27
29
  super
28
30
 
29
- klass.validates(name, inclusion: { in: @value }, allow_nil: true)
31
+ klass.validates(name, inclusion: { in: value }, allow_nil: true)
30
32
  end
31
33
  end
32
34
  end
@@ -3,6 +3,8 @@
3
3
  module JsonModel
4
4
  class TypeSpec
5
5
  class Enum < TypeSpec
6
+ attr_reader(:values)
7
+
6
8
  # @param [Array<Object, nil>] values
7
9
  def initialize(*values)
8
10
  super()
@@ -17,7 +19,7 @@ module JsonModel
17
19
  # @return [Hash]
18
20
  def as_schema(**_options)
19
21
  {
20
- enum: @values,
22
+ enum: values,
21
23
  }.compact
22
24
  end
23
25
 
@@ -26,7 +28,7 @@ module JsonModel
26
28
  def register_validations(name, klass)
27
29
  super
28
30
 
29
- klass.validates(name, inclusion: { in: @values }, allow_nil: true)
31
+ klass.validates(name, inclusion: { in: values }, allow_nil: true)
30
32
  end
31
33
  end
32
34
  end
@@ -3,6 +3,8 @@
3
3
  module JsonModel
4
4
  class TypeSpec
5
5
  class Object < TypeSpec
6
+ attr_reader(:type)
7
+
6
8
  # @param [Schema] type
7
9
  def initialize(type)
8
10
  super()
@@ -12,18 +14,18 @@ module JsonModel
12
14
  # @param [Hash] options
13
15
  # @return [Hash]
14
16
  def as_schema(**options)
15
- @type.as_schema(**options)
17
+ type.as_schema(**options)
16
18
  end
17
19
 
18
20
  # @return [Array<TypeSpec>]
19
21
  def referenced_schemas
20
- [@type]
22
+ [type]
21
23
  end
22
24
 
23
25
  # @param [::Object] json
24
26
  # @return [::Object, nil]
25
27
  def cast(json)
26
- @type.from_json(**json)
28
+ type.from_json(**json)
27
29
  end
28
30
  end
29
31
  end
@@ -32,39 +32,39 @@ module JsonModel
32
32
 
33
33
  class << self
34
34
  # @param [Object, Class] type
35
- # @param [Hash] options
36
35
  # @return [TypeSpec]
37
- def resolve(type, **options)
36
+ def resolve(type)
38
37
  case type
39
38
  when TypeSpec
40
39
  type
41
40
  when Class
42
- resolve_type_from_class(type, **options)
43
- when T::AllOf, T::AnyOf, T::Boolean, T::OneOf, T::Array, T::Enum, T::Const
44
- type.to_type_spec(**options)
41
+ resolve_type_from_class(type)
45
42
  else
46
- raise(ArgumentError, "Unsupported type: #{type}")
43
+ if type.respond_to?(:to_type_spec)
44
+ type.to_type_spec
45
+ else
46
+ raise(ArgumentError, "Unsupported type: #{type}")
47
+ end
47
48
  end
48
49
  end
49
50
 
50
51
  private
51
52
 
52
53
  # @param [Object, Class] type
53
- # @param [Hash] options
54
54
  # @return [TypeSpec]
55
- def resolve_type_from_class(type, **options)
55
+ def resolve_type_from_class(type)
56
56
  if type == String
57
- Primitive::String.new(**options)
57
+ Primitive::String.new
58
58
  elsif type == Integer
59
- Primitive::Integer.new(**options)
59
+ Primitive::Integer.new
60
60
  elsif type == Float
61
- Primitive::Number.new(**options)
61
+ Primitive::Number.new
62
62
  elsif [TrueClass, FalseClass].include?(type)
63
- Primitive::Boolean.new(**options)
63
+ Primitive::Boolean.new
64
64
  elsif type == NilClass
65
- Primitive::Null.new(**options)
65
+ Primitive::Null.new
66
66
  elsif type < Schema
67
- TypeSpec::Object.new(type, **options)
67
+ TypeSpec::Object.new(type)
68
68
  else
69
69
  raise(ArgumentError, "Unsupported type: #{type}")
70
70
  end
@@ -3,23 +3,26 @@
3
3
  module T
4
4
  class AllOf
5
5
  # @param [Array<Class>] types
6
- def initialize(*types)
6
+ # @param [Hash] options
7
+ def initialize(*types, **options)
7
8
  @types = types
9
+ @options = options
8
10
  end
9
11
 
10
12
  # @return [JsonModel::TypeSpec::Composition::AllOf]
11
- def to_type_spec(**options)
13
+ def to_type_spec
12
14
  JsonModel::TypeSpec::Composition::AllOf.new(
13
15
  *@types.map { |type| JsonModel::TypeSpec.resolve(type) },
14
- **options,
16
+ **@options,
15
17
  )
16
18
  end
17
19
 
18
20
  class << self
19
21
  # @param [Array] types
22
+ # @param [Hash] options
20
23
  # @return [AllOf]
21
- def [](*types)
22
- AllOf.new(*types)
24
+ def [](*types, **options)
25
+ AllOf.new(*types, **options)
23
26
  end
24
27
  end
25
28
  end
@@ -3,23 +3,26 @@
3
3
  module T
4
4
  class AnyOf
5
5
  # @param [Array<Class>] types
6
- def initialize(*types)
6
+ # @param [Hash] options
7
+ def initialize(*types, **options)
7
8
  @types = types
9
+ @options = options
8
10
  end
9
11
 
10
12
  # @return [JsonModel::TypeSpec::Composition::AnyOf]
11
- def to_type_spec(**options)
13
+ def to_type_spec
12
14
  JsonModel::TypeSpec::Composition::AnyOf.new(
13
15
  *@types.map { |type| JsonModel::TypeSpec.resolve(type) },
14
- **options,
16
+ **@options,
15
17
  )
16
18
  end
17
19
 
18
20
  class << self
19
21
  # @param [Array] types
22
+ # @param [Hash] options
20
23
  # @return [AnyOf]
21
- def [](*types)
22
- AnyOf.new(*types)
24
+ def [](*types, **options)
25
+ AnyOf.new(*types, **options)
23
26
  end
24
27
  end
25
28
  end
@@ -3,23 +3,26 @@
3
3
  module T
4
4
  class Array
5
5
  # @param [Class] type
6
- def initialize(type)
6
+ # @param [Hash] options
7
+ def initialize(type, **options)
7
8
  @type = type
9
+ @options = options
8
10
  end
9
11
 
10
12
  # @return [JsonModel::TypeSpec::Array]
11
- def to_type_spec(**options)
13
+ def to_type_spec
12
14
  JsonModel::TypeSpec::Array.new(
13
15
  JsonModel::TypeSpec.resolve(@type),
14
- **options,
16
+ **@options,
15
17
  )
16
18
  end
17
19
 
18
20
  class << self
19
21
  # @param [Class] type
22
+ # @param [Hash] options
20
23
  # @return [Array]
21
- def [](type)
22
- Array.new(type)
24
+ def [](type, **options)
25
+ Array.new(type, **options)
23
26
  end
24
27
  end
25
28
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module T
4
4
  Boolean = Class.new do
5
- def to_type_spec(**_options) = JsonModel::TypeSpec::Primitive::Boolean.new
5
+ def to_type_spec = JsonModel::TypeSpec::Primitive::Boolean.new
6
6
  end.new
7
7
  end
@@ -8,8 +8,8 @@ module T
8
8
  end
9
9
 
10
10
  # @return [JsonModel::TypeSpec::Const]
11
- def to_type_spec(**options)
12
- JsonModel::TypeSpec::Const.new(*@value, **options)
11
+ def to_type_spec
12
+ JsonModel::TypeSpec::Const.new(*@value)
13
13
  end
14
14
 
15
15
  class << self
@@ -8,8 +8,8 @@ module T
8
8
  end
9
9
 
10
10
  # @return [JsonModel::TypeSpec::Enum]
11
- def to_type_spec(**options)
12
- JsonModel::TypeSpec::Enum.new(*@values, **options)
11
+ def to_type_spec
12
+ JsonModel::TypeSpec::Enum.new(*@values)
13
13
  end
14
14
 
15
15
  class << self
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module T
4
+ class Integer
5
+ # @param [Hash] options
6
+ def initialize(**options)
7
+ @options = options
8
+ end
9
+
10
+ # @return [JsonModel::TypeSpec::Composition::Primitive::Integer]
11
+ def to_type_spec
12
+ JsonModel::TypeSpec::Primitive::Integer.new(**@options)
13
+ end
14
+
15
+ class << self
16
+ # @param [Hash] options
17
+ # @return [T::Integer]
18
+ def [](**options)
19
+ Integer.new(**options)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module T
4
+ Null = Class.new do
5
+ def to_type_spec = JsonModel::TypeSpec::Primitive::Null.new
6
+ end.new
7
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module T
4
+ class Number
5
+ # @param [Hash] options
6
+ def initialize(**options)
7
+ @options = options
8
+ end
9
+
10
+ # @return [JsonModel::TypeSpec::Composition::Primitive::Number]
11
+ def to_type_spec
12
+ JsonModel::TypeSpec::Primitive::Number.new(**@options)
13
+ end
14
+
15
+ class << self
16
+ # @param [Hash] options
17
+ # @return [Number]
18
+ def [](**options)
19
+ Number.new(**options)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -3,23 +3,26 @@
3
3
  module T
4
4
  class OneOf
5
5
  # @param [Array<Class>] types
6
- def initialize(*types)
6
+ # @param [Hash] options
7
+ def initialize(*types, **options)
7
8
  @types = types
9
+ @options = options
8
10
  end
9
11
 
10
12
  # @return [JsonModel::TypeSpec::Composition::OneOf]
11
- def to_type_spec(**options)
13
+ def to_type_spec
12
14
  JsonModel::TypeSpec::Composition::OneOf.new(
13
15
  *@types.map { |type| JsonModel::TypeSpec.resolve(type) },
14
- **options,
16
+ **@options,
15
17
  )
16
18
  end
17
19
 
18
20
  class << self
19
21
  # @param [Array] types
22
+ # @param [Hash] options
20
23
  # @return [OneOf]
21
- def [](*types)
22
- OneOf.new(*types)
24
+ def [](*types, **options)
25
+ OneOf.new(*types, **options)
23
26
  end
24
27
  end
25
28
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module T
4
+ class String
5
+ # @param [Hash] options
6
+ def initialize(**options)
7
+ @options = options
8
+ end
9
+
10
+ # @return [JsonModel::TypeSpec::Composition::Primitive::String]
11
+ def to_type_spec
12
+ JsonModel::TypeSpec::Primitive::String.new(**@options)
13
+ end
14
+
15
+ class << self
16
+ # @param [Hash] options
17
+ # @return [T::String]
18
+ def [](**options)
19
+ String.new(**options)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,8 +2,12 @@
2
2
 
3
3
  require_relative('types/all_of')
4
4
  require_relative('types/any_of')
5
- require_relative('types/boolean')
6
- require_relative('types/one_of')
7
5
  require_relative('types/array')
6
+ require_relative('types/boolean')
8
7
  require_relative('types/const')
9
8
  require_relative('types/enum')
9
+ require_relative('types/integer')
10
+ require_relative('types/null')
11
+ require_relative('types/number')
12
+ require_relative('types/one_of')
13
+ require_relative('types/string')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JsonModel
4
- VERSION = '0.1.13'
4
+ VERSION = '0.1.15'
5
5
  end
@@ -9,8 +9,8 @@ RSpec.describe('File system schema') do
9
9
  Class.new do
10
10
  include(JsonModel::Schema)
11
11
 
12
- property(:type, type: T::Enum['disk'])
13
- property(:device, type: String, pattern: %r{\A/dev/[^/]+(/[^/]+)*\z})
12
+ property(:type, type: T::Const['disk'])
13
+ property(:device, type: T::String[pattern: %r{\A/dev/[^/]+(/[^/]+)*\z}])
14
14
  end,
15
15
  )
16
16
 
@@ -19,11 +19,10 @@ RSpec.describe('File system schema') do
19
19
  Class.new do
20
20
  include(JsonModel::Schema)
21
21
 
22
- property(:type, type: T::Enum['disk'])
22
+ property(:type, type: T::Enum['diskUUID', 'diskuuid'])
23
23
  property(
24
24
  :label,
25
- type: String,
26
- 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/,
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/],
27
26
  )
28
27
  end,
29
28
  )
@@ -33,9 +32,9 @@ RSpec.describe('File system schema') do
33
32
  Class.new do
34
33
  include(JsonModel::Schema)
35
34
 
36
- property(:type, type: T::Enum['nfs'])
37
- property(:remote_path, type: String, pattern: %r{\A(/[^/]+)+\z}, as: :remotePath)
38
- property(:server, type: String, format: :ipv4)
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])
39
38
  end,
40
39
  )
41
40
 
@@ -44,8 +43,8 @@ RSpec.describe('File system schema') do
44
43
  Class.new do
45
44
  include(JsonModel::Schema)
46
45
 
47
- property(:type, type: T::Enum['tmpfs'])
48
- property(:size_in_mb, type: Integer, minimum: 16, maximum: 512, as: :sizeInMB)
46
+ property(:type, type: T::Const['tmpfs'])
47
+ property(:size_in_mb, type: T::Integer[minimum: 16, maximum: 512], as: :sizeInMB)
49
48
  end,
50
49
  )
51
50
 
@@ -55,9 +54,13 @@ RSpec.describe('File system schema') do
55
54
  include(JsonModel::Schema)
56
55
 
57
56
  description('JSON Schema for an fstab entry')
58
- property(:storage, type: T::OneOf[DiskDevice, DiskUuid, Nfs, Tmpfs], ref_mode: JsonModel::RefMode::LOCAL)
57
+ property(
58
+ :storage,
59
+ type: T::OneOf[DiskDevice, DiskUuid, Nfs, Tmpfs, discriminator: :type],
60
+ ref_mode: JsonModel::RefMode::LOCAL,
61
+ )
59
62
  property(:fstype, type: T::Enum['ext3', 'ext4', 'btrfs'], optional: true)
60
- property(:options, type: T::Array[String], min_items: 1, unique_items: true, optional: true)
63
+ property(:options, type: T::Array[String, min_items: 1, unique_items: true], optional: true)
61
64
  property(:readonly, type: T::Boolean, optional: true)
62
65
  end,
63
66
  )
@@ -100,7 +103,7 @@ RSpec.describe('File system schema') do
100
103
  DiskDevice: {
101
104
  properties: {
102
105
  type: {
103
- enum: ['disk'],
106
+ const: 'disk',
104
107
  },
105
108
  device: {
106
109
  type: 'string',
@@ -113,7 +116,7 @@ RSpec.describe('File system schema') do
113
116
  },
114
117
  DiskUuid: {
115
118
  properties: {
116
- type: { enum: ['disk'] },
119
+ type: { enum: %w(diskUUID diskuuid) },
117
120
  label: {
118
121
  type: 'string',
119
122
  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',
@@ -125,7 +128,7 @@ RSpec.describe('File system schema') do
125
128
  },
126
129
  Nfs: {
127
130
  properties: {
128
- type: { enum: ['nfs'] },
131
+ type: { const: 'nfs' },
129
132
  remotePath: {
130
133
  type: 'string',
131
134
  pattern: '\\A(/[^/]+)+\\z',
@@ -141,7 +144,7 @@ RSpec.describe('File system schema') do
141
144
  },
142
145
  Tmpfs: {
143
146
  properties: {
144
- type: { enum: ['tmpfs'] },
147
+ type: { const: 'tmpfs' },
145
148
  sizeInMB: { type: 'integer', minimum: 16, maximum: 512 },
146
149
  },
147
150
  required: %i(sizeInMB type),
@@ -14,7 +14,7 @@ RSpec.describe('User schema') do
14
14
  property(:street, type: String)
15
15
  property(:city, type: String)
16
16
  property(:state, type: String, optional: true)
17
- property(:postal_code, type: String, pattern: /\A\d{5}(-\d{4})?\z/, optional: true)
17
+ property(:postal_code, type: T::String[pattern: /\A\d{5}(-\d{4})?\z/], optional: true)
18
18
  property(:country, type: String, default: 'USA')
19
19
  end
20
20
 
@@ -28,8 +28,8 @@ RSpec.describe('User schema') do
28
28
  end
29
29
 
30
30
  property(:name, type: String)
31
- property(:email, type: String, format: :email)
32
- property(:age, type: Integer, minimum: 0, maximum: 120, optional: true)
31
+ property(:email, type: T::String[format: :email])
32
+ property(:age, type: T::Integer[minimum: 0, maximum: 120], optional: true)
33
33
  property(:active, type: T::Boolean, default: true, optional: true)
34
34
  property(:addresses, type: T::Array[Address], ref_mode: JsonModel::RefMode::LOCAL)
35
35
  property(:tags, type: T::Array[String], optional: true)
data/spec/schema_spec.rb CHANGED
@@ -44,7 +44,7 @@ RSpec.describe(JsonModel::Schema) do
44
44
  Class.new do
45
45
  include(JsonModel::Schema)
46
46
 
47
- property(:foo, type: String, min_length: 3)
47
+ property(:foo, type: T::String[min_length: 3])
48
48
  end
49
49
  end
50
50
 
@@ -76,7 +76,7 @@ RSpec.describe(JsonModel::Schema) do
76
76
 
77
77
  stub_const(
78
78
  'Bar',
79
- Class.new(Foo) {},
79
+ Class.new(Foo),
80
80
  )
81
81
  end
82
82
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_model_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Gillesberger
@@ -138,7 +138,11 @@ files:
138
138
  - lib/json_model/types/boolean.rb
139
139
  - lib/json_model/types/const.rb
140
140
  - lib/json_model/types/enum.rb
141
+ - lib/json_model/types/integer.rb
142
+ - lib/json_model/types/null.rb
143
+ - lib/json_model/types/number.rb
141
144
  - lib/json_model/types/one_of.rb
145
+ - lib/json_model/types/string.rb
142
146
  - lib/json_model/version.rb
143
147
  - spec/config_spec.rb
144
148
  - spec/examples/component_spec.rb