json_model_rb 0.1.18 → 0.1.20

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: 18911c5ebb83b6699be34560af2a7c8d964ff54c497a135603c3e5e1ae2c8a18
4
- data.tar.gz: 3b2c5736aea3dac28d2a54ba783c0f933284cddf587c76aab20327323cfc876f
3
+ metadata.gz: 98b0c57c0738f93582f7783f5de240050d0129e7015ee2e208101ee2fbf62228
4
+ data.tar.gz: 847d1567156289c42144329ca370250772bdd9fdfa1c4776482d354a51560ab5
5
5
  SHA512:
6
- metadata.gz: 9061ca8854c66c5f9d17f2d5381484b898c395b86d826ef0b2b7a1724d45cf1d297a3427d3fa7ca5e3000aeb262e5336d60f5436e4020064a3de01ea01ee40e2
7
- data.tar.gz: 946fc6b81294a7eda74add39544f079691b032158f5de0a58e0b241a35ab66629a0398145273e7645bdc5614046d574e28879765cd04f4b104e69dc285e80e09
6
+ metadata.gz: a8eb301c456c28814b8b7eca3fbbe30a0d7c6e8e789bbc6bbfca73052e0f18934e277913a1cc7632a45fe56245781389bc96ed8d59b01781d63ec08f3c2f0f61
7
+ data.tar.gz: 9ae72f4ab9291f822ed7dcb632744c4b87c8689344fcb3bb68ea469ea605fa57945735af341c1671edcfe2d4b91a8a73ece88fa72c092b9027860f8d1da73d74
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonModel
4
+ module Composeable
5
+ extend(ActiveSupport::Concern)
6
+
7
+ class_methods do
8
+ # @return [Array]
9
+ def composed_types
10
+ @composed_types ||= []
11
+ end
12
+
13
+ # @param [Object] type
14
+ # @param [Symbol] ref_mode
15
+ def compose(type, ref_mode: RefMode::LOCAL)
16
+ composed_types << {
17
+ type: TypeSpec.resolve(type),
18
+ ref_mode: ref_mode,
19
+ }
20
+ end
21
+
22
+ # @return [Array<JsonModel::TypeSpec::Composition>]
23
+ def composed_type_defs
24
+ composed_types.select { |type| type[:ref_mode] == RefMode::LOCAL }.flat_map { |it| it[:type].referenced_schemas }
25
+ end
26
+
27
+ # @return [Array<Hash>]
28
+ def composed_types_as_schema
29
+ composed_types.each_with_object({}) do |it, agg|
30
+ agg.deep_merge!(it[:type].as_schema(ref_mode: it[:ref_mode]))
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -3,6 +3,7 @@
3
3
  module JsonModel
4
4
  module Schema
5
5
  extend(ActiveSupport::Concern)
6
+ include(Composeable)
6
7
  include(Properties)
7
8
  include(SchemaMeta)
8
9
 
@@ -61,6 +62,7 @@ module JsonModel
61
62
  required: required_properties_as_schema,
62
63
  '$defs': defs_as_schema,
63
64
  )
65
+ .merge(**composed_types_as_schema)
64
66
  .merge(type: 'object')
65
67
  .compact
66
68
  when RefMode::LOCAL
@@ -94,11 +96,7 @@ module JsonModel
94
96
  end
95
97
 
96
98
  def defs_as_schema
97
- referenced_schemas = local_properties
98
- .values
99
- .flat_map(&:referenced_schemas)
100
- .uniq
101
-
99
+ referenced_schemas = (composed_type_defs + local_properties.values.flat_map(&:referenced_schemas)).uniq
102
100
  if referenced_schemas.any?
103
101
  referenced_schemas.to_h { |type| [type.name.to_sym, type.as_schema] }
104
102
  end
@@ -49,17 +49,18 @@ module JsonModel
49
49
  # @param [Object, Class] type
50
50
  # @return [TypeSpec]
51
51
  def resolve(type)
52
- case type
53
- when TypeSpec
54
- type
55
- when Class
56
- resolve_type_from_class(type)
52
+ if type.is_a?(TypeSpec)
53
+ return type
54
+ end
55
+
56
+ if TYPE_MAP.key?(type)
57
+ TYPE_MAP[type]
58
+ elsif type.respond_to?(:to_type_spec)
59
+ type.to_type_spec
60
+ elsif type.is_a?(Class) && type < Schema
61
+ TypeSpec::Object.new(type)
57
62
  else
58
- if type.respond_to?(:to_type_spec)
59
- type.to_type_spec
60
- else
61
- raise(ArgumentError, "Unsupported type: #{type}")
62
- end
63
+ raise(ArgumentError, "Unsupported type: #{type}")
63
64
  end
64
65
  end
65
66
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JsonModel
4
- VERSION = '0.1.18'
4
+ VERSION = '0.1.20'
5
5
  end
data/lib/json_model.rb CHANGED
@@ -5,6 +5,7 @@ require('active_support/concern')
5
5
  require('active_support/core_ext/class/attribute')
6
6
  require('active_support/descendants_tracker')
7
7
  require('uri')
8
+ require('json_model/composeable')
8
9
  require('json_model/config')
9
10
  require('json_model/errors')
10
11
  require('json_model/properties')
@@ -20,20 +20,35 @@ RSpec.describe('User schema') do
20
20
 
21
21
  stub_const('Address', address_class)
22
22
 
23
- user_class = Class.new do
23
+ person_class = Class.new do
24
24
  include(JsonModel::Schema)
25
25
 
26
26
  def self.name
27
- 'User'
27
+ 'Person'
28
28
  end
29
29
 
30
+ schema_id('person.schema.json')
30
31
  property(:name, type: String)
31
32
  property(:email, type: T::String[format: :email])
33
+ end
34
+
35
+ stub_const('Person', person_class)
36
+
37
+ user_class = Class.new do
38
+ include(JsonModel::Schema)
39
+
40
+ def self.name
41
+ 'User'
42
+ end
43
+
44
+ compose(T::AllOf[Person], ref_mode: JsonModel::RefMode::EXTERNAL)
32
45
  property(:age, type: T::Integer[minimum: 0, maximum: 120], optional: true)
33
46
  property(:active, type: T::Boolean, default: true, optional: true)
34
47
  property(:addresses, type: T::Array[Address], ref_mode: JsonModel::RefMode::LOCAL)
35
48
  property(:tags, type: T::Array[String], optional: true)
36
49
  property(:birthday, type: Date, optional: true)
50
+ property(:websites, type: T::Array[URI], optional: true)
51
+ property(:height, type: Float, optional: true)
37
52
  end
38
53
 
39
54
  stub_const('User', user_class)
@@ -45,9 +60,8 @@ RSpec.describe('User schema') do
45
60
  eq(
46
61
  {
47
62
  type: 'object',
63
+ allOf: [{ '$ref': 'person.schema.json' }],
48
64
  properties: {
49
- name: { type: 'string' },
50
- email: { type: 'string', format: 'email' },
51
65
  age: { type: 'integer', minimum: 0, maximum: 120 },
52
66
  active: { type: 'boolean', default: true },
53
67
  addresses: {
@@ -56,8 +70,10 @@ RSpec.describe('User schema') do
56
70
  },
57
71
  tags: { type: 'array', items: { type: 'string' } },
58
72
  birthday: { type: 'string', format: 'date' },
73
+ websites: { type: 'array', items: { type: 'string', format: 'uri' } },
74
+ height: { type: 'number' },
59
75
  },
60
- required: %i(addresses email name),
76
+ required: %i(addresses),
61
77
  '$defs': {
62
78
  Address: {
63
79
  type: 'object',
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_model_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.18
4
+ version: 0.1.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Gillesberger
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-01-05 00:00:00.000000000 Z
10
+ date: 2026-01-19 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rake
@@ -103,6 +103,7 @@ files:
103
103
  - LICENSE
104
104
  - README.md
105
105
  - lib/json_model.rb
106
+ - lib/json_model/composeable.rb
106
107
  - lib/json_model/config.rb
107
108
  - lib/json_model/config/options.rb
108
109
  - lib/json_model/errors.rb