serega 0.12.0 → 0.14.0

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: 52535c7fab3897f65aec4e156ab5681e8595b4519df1e79a777688cee486a480
4
- data.tar.gz: 16adbd9f036b0e23928049df873966f264db1004d2c4c1bc9e28422d687efd12
3
+ metadata.gz: f11821b5953500ef9f895ad8c96e97951734615363f3147c623b70519b6199a5
4
+ data.tar.gz: 8b03241a9def2e5a8777a75e61062f8b81544e497a1a1e490e085d52f14a326c
5
5
  SHA512:
6
- metadata.gz: 93a6aaefdf954556e31bd604ead1e376d5ffbb74225251e635bf5133af53da26f47e924f1f88349fa4656e228ddca573347d9f8fa15cc30bc6052f7e5dfec3bd
7
- data.tar.gz: c84135d04c79aae1ccd03a3f3ac7dbed53dbf75165575afbb61ad6e32a558318cac2a8311c31b76df90fb74823facdf4677821d8f7ae8284f04782d33b04ad41
6
+ metadata.gz: eb5cb48e74c0e9c8307c6ceb6c47b918eb46ef3c160de90d0eb976239bbc036f1d3fb78219abd5567977f348e3e03d7e492e29140e6d85223fcf14289d794d89
7
+ data.tar.gz: acb7623ea317aab640aae70d0a5dfa0c436b706529741b36b15d938ab6af7523576f72ab4633b591b61dcdc38df768818eab3811005c248c3a00d2872cdccc46
data/README.md CHANGED
@@ -888,6 +888,107 @@ Look at [select serialized fields](#selecting-fields) for `:hide` usage examples
888
888
  end
889
889
  ```
890
890
 
891
+ ### Plugin :openapi
892
+
893
+ Helps to build OpenAPI schemas
894
+
895
+ This schemas can be easily used with [rswag](https://github.com/rswag/rswag#referenced-parameters-and-schema-definitions)"
896
+ gem by adding them to "config.swagger_docs"
897
+
898
+ Schemas properties will have no any "type" or other limits specified by default,
899
+ you should provide them as new attribute `:openapi` option.
900
+
901
+ This plugin adds type "object" or "array" only for relationships and marks
902
+ attributes as **required** if they have no `:hide` option set
903
+ (manually or automatically).
904
+
905
+ After enabling this plugin attributes with :serializer option will have
906
+ to have `:many` option set to construct "object" or "array" openapi
907
+ property type.
908
+
909
+ - constructing all serializers schemas:
910
+ `Serega::OpenAPI.schemas`
911
+ - constructing specific serializers schemas:
912
+ `Serega::OpenAPI.schemas(Serega::OpenAPI.serializers - [MyBaseSerializer])`
913
+ - constructing one serializer schema:
914
+ `SomeSerializer.openapi_schema`
915
+
916
+ ```ruby
917
+ class BaseSerializer < Serega
918
+ plugin :openapi
919
+ end
920
+
921
+ class UserSerializer < BaseSerializer
922
+ attribute :name, openapi: { type: "string" }
923
+
924
+ openapi_properties(
925
+ name: { type: :string }
926
+ )
927
+ end
928
+
929
+ class PostSerializer < BaseSerializer
930
+ attribute :text, openapi: { type: "string" }
931
+ attribute :user, serializer: UserSerializer, many: false
932
+ attribute :comments, serializer: PostSerializer, many: true, hide: true
933
+
934
+ openapi_properties(
935
+ text: { type: :string },
936
+ user: { type: 'object' }, # `$ref` added automatically
937
+ comments: { type: 'array' } # `items` option with `$ref` added automatically
938
+ )
939
+ end
940
+
941
+ puts Serega::OpenAPI.schemas
942
+ # =>
943
+ # {
944
+ # "PostSerializer" => {
945
+ # type: "object",
946
+ # properties: {
947
+ # text: {type: "string"},
948
+ # user: {:$ref => "#/components/schemas/UserSerializer"},
949
+ # comments: {type: "array", items: {:$ref => "#/components/schemas/PostSerializer"}}
950
+ # },
951
+ # required: [:text, :comments],
952
+ # additionalProperties: false
953
+ # },
954
+ # "UserSerializer" => {
955
+ # type: "object",
956
+ # properties: {
957
+ # name: {type: "string"}
958
+ # },
959
+ # required: [:name],
960
+ # additionalProperties: false
961
+ # }
962
+ # }
963
+ ```
964
+
965
+ ### Plugin :explicit_many_option
966
+
967
+ Plugin requires to add :many option when adding relationships
968
+ (relationships are attributes with :serializer option specified)
969
+
970
+ Adding this plugin makes clearer to find if relationship returns array or single
971
+ object
972
+
973
+ Also plugin `:openapi` load this plugin automatically as it need to know if
974
+ relationship is array
975
+
976
+ ```ruby
977
+ class BaseSerializer < Serega
978
+ plugin :explicit_many_option
979
+ end
980
+
981
+ class UserSerializer < BaseSerializer
982
+ attribute :name
983
+ end
984
+
985
+ class PostSerializer < BaseSerializer
986
+ attribute :text
987
+ attribute :user, serializer: UserSerializer, many: false
988
+ attribute :comments, serializer: PostSerializer, many: true
989
+ end
990
+ ```
991
+
891
992
  ## Errors
892
993
 
893
994
  - `Serega::SeregaError` is a base error raised by this gem.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.12.0
1
+ 0.14.0
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ #
6
+ # Plugin :explicit_many_option
7
+ #
8
+ # Plugin requires to add :many option when adding relationships
9
+ # (relationships are attributes with :serializer option specified)
10
+ #
11
+ # Adding this plugin makes clearer to find if relationship returns array or single object
12
+ #
13
+ # Also some plugins like :openapi load this plugin automatically as they need to know if
14
+ # relationship is array
15
+ #
16
+ # @example
17
+ # class BaseSerializer < Serega
18
+ # plugin :explicit_many_option
19
+ # end
20
+ #
21
+ # class UserSerializer < BaseSerializer
22
+ # attribute :name
23
+ # end
24
+ #
25
+ # class PostSerializer < BaseSerializer
26
+ # attribute :text
27
+ # attribute :user, serializer: UserSerializer, many: false
28
+ # attribute :comments, serializer: PostSerializer, many: true
29
+ # end
30
+ #
31
+ module ExplicitManyOption
32
+ # @return [Symbol] Plugin name
33
+ def self.plugin_name
34
+ :explicit_many_option
35
+ end
36
+
37
+ #
38
+ # Applies plugin code to specific serializer
39
+ #
40
+ # @param serializer_class [Class<Serega>] Current serializer class
41
+ # @param _opts [Hash] Loaded plugins options
42
+ #
43
+ # @return [void]
44
+ #
45
+ def self.load_plugin(serializer_class, **_opts)
46
+ require_relative "./validations/check_opt_many"
47
+
48
+ serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
49
+ end
50
+
51
+ #
52
+ # Serega::SeregaValidations::CheckAttributeParams additional/patched class methods
53
+ #
54
+ # @see Serega::SeregaValidations::CheckAttributeParams
55
+ #
56
+ module CheckAttributeParamsInstanceMethods
57
+ private
58
+
59
+ def check_opts
60
+ super
61
+
62
+ CheckOptMany.call(opts)
63
+ end
64
+ end
65
+ end
66
+
67
+ register_plugin(ExplicitManyOption.plugin_name, ExplicitManyOption)
68
+ end
69
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ module ExplicitManyOption
6
+ #
7
+ # Validator for attribute :many option
8
+ #
9
+ class CheckOptMany
10
+ class << self
11
+ #
12
+ # Checks attribute :many option must be provided with relations
13
+ #
14
+ # @param opts [Hash] Attribute options
15
+ #
16
+ # @raise [SeregaError] Attribute validation error
17
+ #
18
+ # @return [void]
19
+ #
20
+ def call(opts)
21
+ serializer = opts[:serializer]
22
+ return unless serializer
23
+
24
+ many_option_exists = opts.key?(:many)
25
+ return if many_option_exists
26
+
27
+ raise SeregaError,
28
+ "Attribute option :many [Boolean] must be provided" \
29
+ " for attributes with :serializer option"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ module OpenAPI
6
+ #
7
+ # Config class additional/patched instance methods
8
+ #
9
+ # @see Serega::SeregaConfig
10
+ #
11
+ module ConfigInstanceMethods
12
+ #
13
+ # Returns openapi plugin config
14
+ #
15
+ # @return [Serega::SeregaPlugins::OpenAPI::OpenAPIConfig] configuration for openapi plugin
16
+ #
17
+ def openapi
18
+ @openapi ||= OpenAPIConfig.new(self.class.serializer_class, opts.fetch(:openapi))
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ module OpenAPI
6
+ #
7
+ # OpenAPI plugin config
8
+ #
9
+ class OpenAPIConfig
10
+ attr_reader :serializer_class, :opts
11
+
12
+ def initialize(serializer_class, opts)
13
+ @serializer_class = serializer_class
14
+ @opts = opts
15
+ end
16
+
17
+ #
18
+ # Saves new properties
19
+ #
20
+ # @param new_properties [Hash] new properties
21
+ #
22
+ # @return [Hash] OpenAPI properties
23
+ #
24
+ def properties(new_properties = FROZEN_EMPTY_HASH)
25
+ properties = opts[:properties]
26
+ return properties if new_properties.empty?
27
+
28
+ new_properties = SeregaUtils::EnumDeepDup.call(new_properties)
29
+ symbolize_keys!(new_properties)
30
+
31
+ new_properties.each do |attribute_name, new_attribute_properties|
32
+ check_attribute_exists(attribute_name)
33
+ check_properties_is_a_hash(attribute_name, new_attribute_properties)
34
+
35
+ properties[attribute_name] = symbolize_keys!(new_attribute_properties)
36
+ end
37
+ end
38
+
39
+ #
40
+ # @return [#call] builder of `$ref` attribute
41
+ #
42
+ def ref_builder
43
+ opts[:ref_builder]
44
+ end
45
+
46
+ #
47
+ # Sets new $ref option builder
48
+ #
49
+ # @param builder [#call] Callable object that accepts serializer_class and constructs $ref option string
50
+ #
51
+ # @return Specified new builder
52
+ #
53
+ def ref_builder=(builder)
54
+ raise SeregaError, "ref_builder must respond to #call" unless builder.respond_to?(:call)
55
+ opts[:ref_builder] = builder
56
+ end
57
+
58
+ #
59
+ # @return [#call] builder of schema name
60
+ #
61
+ def schema_name_builder
62
+ opts[:schema_name_builder]
63
+ end
64
+
65
+ #
66
+ # Sets new schema_name_builder
67
+ #
68
+ # @param builder [#call] Callable object that accepts serializer_class and
69
+ # constructs schema name to use in schemas list and in $ref option
70
+ #
71
+ # @return Specified new builder
72
+ #
73
+ def schema_name_builder=(builder)
74
+ raise SeregaError, "schema_name_builder must respond to #call" unless builder.respond_to?(:call)
75
+ opts[:schema_name_builder] = builder
76
+ end
77
+
78
+ private
79
+
80
+ def check_attribute_exists(attribute_name)
81
+ return if serializer_class.attributes.key?(attribute_name)
82
+
83
+ raise SeregaError, "No attribute with name :#{attribute_name}"
84
+ end
85
+
86
+ def check_properties_is_a_hash(attribute_name, new_attribute_properties)
87
+ return if new_attribute_properties.is_a?(Hash)
88
+
89
+ raise SeregaError, "Property #{attribute_name} value must be a Hash," \
90
+ " but #{new_attribute_properties.inspect} was provided"
91
+ end
92
+
93
+ def symbolize_keys!(opts)
94
+ opts.transform_keys! do |key|
95
+ key.to_sym
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,245 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ #
5
+ # Utility class to build OpenAPI schemas
6
+ #
7
+ class OpenAPI
8
+ #
9
+ # Constructs OpenAPI schemas for multiple serializers
10
+ #
11
+ # @params serializers [Class<Serega>] Serializers tobuild schemas,
12
+ # by default it is all serializers with :openapi plugin enabled
13
+ #
14
+ # @return [Hash] Schemas hash
15
+ #
16
+ def self.schemas(serializers = self.serializers)
17
+ serializers.each_with_object({}) do |serializer_class, schemas|
18
+ schema = serializer_class.openapi_schema
19
+ schema_name = serializer_class.openapi_schema_name
20
+ schemas[schema_name] = schema
21
+ end
22
+ end
23
+
24
+ #
25
+ # Returns list of serializers with :openapi plugin
26
+ #
27
+ def self.serializers
28
+ @serializers ||= []
29
+ end
30
+ end
31
+
32
+ module SeregaPlugins
33
+ #
34
+ # Plugin :openapi
35
+ #
36
+ # Helps to build OpenAPI schemas
37
+ #
38
+ # This schemas can be easielty used with "rswag" gem by adding them to "config.swagger_docs"
39
+ # https://github.com/rswag/rswag#referenced-parameters-and-schema-definitions
40
+ #
41
+ # This plugin only adds type "object" or "array" for relationships and marks
42
+ # attributes as **required** if they have no :hide option set.
43
+ #
44
+ # OpenAPI properties will have no any "type" or other options specified by default,
45
+ # you should provide them in 'YourSerializer.openapi_properties' method.
46
+ # `openapi_properties` can be specified multiple time, in this case they wil be merged.
47
+ #
48
+ # After enabling this plugin attributes with :serializer option will have
49
+ # to have :many option set to construct "object" or "array" openapi type for relationships.
50
+ #
51
+ # OpenAPI `$ref` property will be added automatically for all relationships.
52
+ #
53
+ # Example constructing all serializers schemas:
54
+ # `Serega::OpenAPI.schemas`
55
+ #
56
+ # Example constructing specific serializers schemas:
57
+ # `Serega::OpenAPI.schemas(Serega::OpenAPI.serializers - [MyBaseSerializer])`
58
+ #
59
+ # Example constructing one serializer schema:
60
+ # `SomeSerializer.openapi_schema`
61
+ #
62
+ # @example
63
+ # class BaseSerializer < Serega
64
+ # plugin :openapi
65
+ # end
66
+ #
67
+ # class UserSerializer < BaseSerializer
68
+ # attribute :name
69
+ #
70
+ # openapi_properties(
71
+ # name: { type: :string }
72
+ # )
73
+ # end
74
+ #
75
+ # class PostSerializer < BaseSerializer
76
+ # attribute :text
77
+ # attribute :user, serializer: UserSerializer, many: false
78
+ # attribute :comments, serializer: PostSerializer, many: true, hide: true
79
+ #
80
+ # openapi_properties(
81
+ # text: { type: :string },
82
+ # user: { type: 'object' }, # `$ref` option will be added automatically when constructing schema
83
+ # comments: { type: 'array' } # `items` option with `$ref` will be added automatically when constructing schema
84
+ # )
85
+ # end
86
+ #
87
+ # puts Serega::OpenAPI.schemas
88
+ # =>
89
+ # {
90
+ # "PostSerializer" => {
91
+ # type: "object",
92
+ # properties: {
93
+ # text: {type: "string"},
94
+ # user: {:$ref => "#/components/schemas/UserSerializer"},
95
+ # comments: {type: "array", items: {:$ref => "#/components/schemas/PostSerializer"}}
96
+ # },
97
+ # required: [:text, :comments],
98
+ # additionalProperties: false
99
+ # },
100
+ # "UserSerializer" => {
101
+ # type: "object",
102
+ # properties: {
103
+ # name: {type: "string"}
104
+ # },
105
+ # required: [:name],
106
+ # additionalProperties: false
107
+ # }
108
+ # }
109
+ #
110
+ module OpenAPI
111
+ # Builder for schema name (used is schemas list). Returns serializer class name
112
+ DEFAULT_SCHEMA_NAME_BUILDER = ->(serializer_class) { serializer_class.name }
113
+
114
+ # Builder for $ref openapi property
115
+ DEFAULT_REF_BUILDER = ->(serializer_class) { "#/components/schemas/#{serializer_class.openapi_schema_name}" }
116
+
117
+ # @return [Symbol] Plugin name
118
+ def self.plugin_name
119
+ :openapi
120
+ end
121
+
122
+ # Checks requirements and loads additional plugins
123
+ #
124
+ # @param serializer_class [Class<Serega>] Current serializer class
125
+ # @param opts [Hash] loaded plugins opts
126
+ #
127
+ # @return [void]
128
+ #
129
+ def self.before_load_plugin(serializer_class, **opts)
130
+ unless serializer_class.plugin_used?(:explicit_many_option)
131
+ serializer_class.plugin :explicit_many_option
132
+ end
133
+ end
134
+
135
+ #
136
+ # Applies plugin code to specific serializer
137
+ #
138
+ # @param serializer_class [Class<Serega>] Current serializer class
139
+ # @param _opts [Hash] Loaded plugins options
140
+ #
141
+ # @return [void]
142
+ #
143
+ def self.load_plugin(serializer_class, **opts)
144
+ require_relative "./lib/modules/config"
145
+ require_relative "./lib/openapi_config"
146
+
147
+ serializer_class.extend(ClassMethods)
148
+ serializer_class::SeregaConfig.include(ConfigInstanceMethods)
149
+
150
+ config = serializer_class.config
151
+ config.opts[:openapi] = {properties: {}}
152
+ openapi_config = serializer_class.config.openapi
153
+ openapi_config.schema_name_builder = opts[:schema_name_builder] || DEFAULT_SCHEMA_NAME_BUILDER
154
+ openapi_config.ref_builder = opts[:ref_builder] || DEFAULT_REF_BUILDER
155
+ end
156
+
157
+ #
158
+ # Adds config options and runs other callbacks after plugin was loaded
159
+ #
160
+ # @param serializer_class [Class<Serega>] Current serializer class
161
+ # @param opts [Hash] loaded plugins opts
162
+ #
163
+ # @return [void]
164
+ #
165
+ def self.after_load_plugin(serializer_class, **opts)
166
+ Serega::OpenAPI.serializers << serializer_class unless serializer_class.equal?(Serega)
167
+ end
168
+
169
+ #
170
+ # Serega additional/patched class methods
171
+ #
172
+ # @see Serega
173
+ #
174
+ module ClassMethods
175
+ #
176
+ # OpenAPI schema for current serializer
177
+ #
178
+ def openapi_schema
179
+ properties = SeregaUtils::EnumDeepDup.call(openapi_properties)
180
+ required_properties = []
181
+
182
+ attributes.each do |attribute_name, attribute|
183
+ add_openapi_property(properties, attribute_name, attribute)
184
+ add_openapi_required_property(required_properties, attribute_name, attribute)
185
+ end
186
+
187
+ {
188
+ type: "object",
189
+ properties: properties,
190
+ required: required_properties,
191
+ additionalProperties: false
192
+ }
193
+ end
194
+
195
+ #
196
+ # Adds new OpenAPI properties and returns all properties
197
+ #
198
+ # @param props [Hash] Specifies new properties
199
+ #
200
+ # @return [Hash] Specified OpenAPI properties
201
+ #
202
+ def openapi_properties(props = FROZEN_EMPTY_HASH)
203
+ config.openapi.properties(props)
204
+ end
205
+
206
+ #
207
+ # Builds OpenAPI schema name using configured builder
208
+ #
209
+ # @return [String] OpenAPI schema name
210
+ #
211
+ def openapi_schema_name
212
+ config.openapi.schema_name_builder.call(self)
213
+ end
214
+
215
+ private
216
+
217
+ def inherited(subclass)
218
+ super
219
+ Serega::OpenAPI.serializers << subclass
220
+ end
221
+
222
+ def add_openapi_property(properties, attribute_name, attribute)
223
+ property = properties[attribute_name] ||= {}
224
+ return unless attribute.relation?
225
+
226
+ ref = attribute.serializer.config.openapi.ref_builder.call(attribute.serializer)
227
+
228
+ if attribute.many
229
+ property[:type] = "array"
230
+ property[:items] ||= {}
231
+ property[:items][:$ref] ||= ref
232
+ else
233
+ property[:$ref] ||= ref
234
+ end
235
+ end
236
+
237
+ def add_openapi_required_property(required_properties, attribute_name, attribute)
238
+ required_properties << attribute_name unless attribute.hide
239
+ end
240
+ end
241
+ end
242
+
243
+ register_plugin(OpenAPI.plugin_name, OpenAPI)
244
+ end
245
+ end
@@ -11,11 +11,11 @@ class Serega
11
11
  attr_reader :opts
12
12
 
13
13
  #
14
- # Initializes context_metadata config object
14
+ # Initializes PreloadsConfig object
15
15
  #
16
16
  # @param opts [Hash] options
17
17
  #
18
- # @return [Serega::SeregaPlugins::Metadata::MetadataConfig]
18
+ # @return [Serega::SeregaPlugins::Preloads::PreloadsConfig]
19
19
  #
20
20
  def initialize(opts)
21
21
  @opts = opts
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serega
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Glushkov
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-10 00:00:00.000000000 Z
11
+ date: 2023-07-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  JSON Serializer
@@ -59,6 +59,8 @@ files:
59
59
  - lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb
60
60
  - lib/serega/plugins/batch/lib/validations/check_opt_batch.rb
61
61
  - lib/serega/plugins/context_metadata/context_metadata.rb
62
+ - lib/serega/plugins/explicit_many_option/explicit_many_option.rb
63
+ - lib/serega/plugins/explicit_many_option/validations/check_opt_many.rb
62
64
  - lib/serega/plugins/formatters/formatters.rb
63
65
  - lib/serega/plugins/if/if.rb
64
66
  - lib/serega/plugins/if/validations/check_opt_if.rb
@@ -72,6 +74,9 @@ files:
72
74
  - lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb
73
75
  - lib/serega/plugins/metadata/validations/check_opts.rb
74
76
  - lib/serega/plugins/metadata/validations/check_path.rb
77
+ - lib/serega/plugins/openapi/lib/modules/config.rb
78
+ - lib/serega/plugins/openapi/lib/openapi_config.rb
79
+ - lib/serega/plugins/openapi/openapi.rb
75
80
  - lib/serega/plugins/preloads/lib/format_user_preloads.rb
76
81
  - lib/serega/plugins/preloads/lib/modules/attribute.rb
77
82
  - lib/serega/plugins/preloads/lib/modules/attribute_normalizer.rb
@@ -117,7 +122,7 @@ metadata:
117
122
  source_code_uri: https://github.com/aglushkov/serega
118
123
  documentation_uri: https://www.rubydoc.info/gems/serega
119
124
  changelog_uri: https://github.com/aglushkov/serega/blob/master/CHANGELOG.md
120
- post_install_message:
125
+ post_install_message:
121
126
  rdoc_options: []
122
127
  require_paths:
123
128
  - lib
@@ -132,8 +137,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
137
  - !ruby/object:Gem::Version
133
138
  version: '0'
134
139
  requirements: []
135
- rubygems_version: 3.4.7
136
- signing_key:
140
+ rubygems_version: 3.4.6
141
+ signing_key:
137
142
  specification_version: 4
138
143
  summary: JSON Serializer
139
144
  test_files: []