Skip to content

Commit b189b85

Browse files
committed
feat: add description field
1 parent 9b16a3c commit b189b85

File tree

4 files changed

+22
-19
lines changed

4 files changed

+22
-19
lines changed

shard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: json-schema
2-
version: 1.2.0
2+
version: 1.2.1
33

44
development_dependencies:
55
ameba:

spec/json_schema_spec.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ describe JSON::Schema do
7777
array: {type: "array", items: {anyOf: [{type: "integer", format: "Int32"}, {type: "string"}]}},
7878
tuple: {type: "array", items: [{type: "string"}, {type: "integer", format: "Int32"}, {type: "number", format: "Float64"}]},
7979
named_tuple: {type: "object", properties: {test: {type: "string"}, other: {type: "integer", format: "Int64"}}, required: ["test", "other"]},
80-
union_type: {anyOf: [{type: "boolean"}, {type: "integer", format: "Int64"}, {type: "string"}]},
80+
union_type: {anyOf: [{type: "boolean"}, {type: "integer", format: "Int64"}, {type: "string"}], description: "a string an int or a bool"},
8181
},
8282
required: ["sub_object", "array", "tuple", "named_tuple", "union_type"],
8383
})

spec/spec_helper.cr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class Example2
3030
getter array : Array(String | Int32)
3131
getter tuple : Tuple(String, Int32, Float64)
3232
getter named_tuple : NamedTuple(test: String, other: Int64)
33+
34+
@[JSON::Field(description: "a string an int or a bool")]
3335
getter union_type : String | Int64 | Bool
3436
end
3537

src/json-schema.cr

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ module JSON
5757
{% format_hint = (args && args[:format]) %}
5858
{% type_override = (args && args[:type]) %}
5959
{% pattern = (args && args[:pattern]) %}
60+
{% description = (args && args[:description]) %}
6061

6162
{% arg_name = klass.stringify %}
6263
{% if !arg_name.starts_with?("Union") && arg_name.includes?("|") %}
@@ -69,16 +70,16 @@ module JSON
6970
{% if klass <= Array || klass <= Set %}
7071
{% if klass.type_vars.size == 1 %}
7172
%has_items = ::JSON::Schema.introspect({{klass.type_vars[0]}}, nil, {{openapi}})
72-
{type: "array", items: %has_items}
73+
{type: "array"{% if description %}, description: {{description}}{% end %}, items: %has_items}
7374
{% else %}
7475
# handle inheritance (no access to type_var / unknown value)
7576
%klass = {{klass.ancestors[0]}}
76-
%klass.responds_to?(:json_schema) ? %klass.json_schema : {type: "array"}
77+
%klass.responds_to?(:json_schema) ? %klass.json_schema({{openapi}}) : { type: "array"{% if description %}, description: {{description}}{% end %} }
7778
{% end %}
7879
{% elsif klass.union? && !openapi.nil? && nillable && klass.union_types.size == 2 %}
7980
{% for type in klass.union_types %}
8081
{% if type.stringify != "Nil" %}
81-
::JSON::Schema.introspect({{type}}, nil, {{openapi}}).merge({
82+
::JSON::Schema.introspect({{type}}, {{args}}, {{openapi}}).merge({
8283
nullable: true
8384
})
8485
{% end %}
@@ -90,19 +91,19 @@ module JSON
9091
::JSON::Schema.introspect({{type}}, nil, {{openapi}}),
9192
{% end %}
9293
{% end %}
93-
]{% if !openapi.nil? && nillable %}, nullable: true{% end %} }
94+
]{% if !openapi.nil? && nillable %}, nullable: true{% end %}{% if description %}, description: {{description}}{% end %} }
9495
{% elsif klass_name.starts_with? "Tuple(" %}
9596
%has_items = [
9697
{% for generic in klass.type_vars %}
9798
::JSON::Schema.introspect({{generic}}, nil, {{openapi}}),
9899
{% end %}
99100
]
100-
{type: "array", items: %has_items}
101+
{type: "array"{% if description %}, description: {{description}}{% end %}, items: %has_items}
101102
{% elsif klass_name.starts_with? "NamedTuple(" %}
102103
{% if klass.keys.empty? %}
103-
{type: "object", properties: {} of Symbol => Nil}
104+
{type: "object"{% if description %}, description: {{description}}{% end %}, properties: {} of Symbol => Nil}
104105
{% else %}
105-
{type: "object", properties: {
106+
{type: "object"{% if description %}, description: {{description}}{% end %}, properties: {
106107
{% for key in klass.keys %}
107108
{{key.id}}: ::JSON::Schema.introspect({{klass[key].resolve.name}}, nil, {{openapi}}),
108109
{% end %}
@@ -123,37 +124,37 @@ module JSON
123124
}
124125
{% end %}
125126
{% elsif klass < Enum %}
126-
{type: "string", enum: {{klass.constants.map(&.stringify.underscore)}} }
127+
{type: "string", enum: {{klass.constants.map(&.stringify.underscore)}}{% if description %}, description: {{description}}{% end %} }
127128
{% elsif klass <= String || klass <= Symbol %}
128129
{% min_length = (args && args[:min_length]) %}
129130
{% max_length = (args && args[:max_length]) %}
130-
{ type: {{type_override || "string"}}{% if format_hint %}, format: {{format_hint}}{% end %}{% if pattern %}, pattern: {{pattern}}{% end %}{% if min_length %}, minLength: {{min_length}}{% end %}{% if max_length %}, maxLength: {{max_length}}{% end %} }
131+
{ type: {{type_override || "string"}}{% if format_hint %}, format: {{format_hint}}{% end %}{% if pattern %}, pattern: {{pattern}}{% end %}{% if min_length %}, minLength: {{min_length}}{% end %}{% if max_length %}, maxLength: {{max_length}}{% end %}{% if description %}, description: {{description}}{% end %} }
131132
{% elsif klass <= Bool %}
132-
{ type: {{type_override || "boolean"}}{% if format_hint %}, format: {{format_hint}}{% end %} }
133+
{ type: {{type_override || "boolean"}}{% if format_hint %}, format: {{format_hint}}{% end %}{% if description %}, description: {{description}}{% end %} }
133134
{% elsif klass <= Int || klass <= Float %}
134135
{% multiple_of = (args && args[:multiple_of]) %}
135136
{% minimum = (args && args[:minimum]) %}
136137
{% exclusive_minimum = (args && args[:exclusive_minimum]) %}
137138
{% maximum = (args && args[:maximum]) %}
138139
{% exclusive_maximum = (args && args[:exclusive_maximum]) %}
139140
{% if klass <= Int %}
140-
{ type: {{type_override || "integer"}}, format: {{format_hint || klass.stringify}}{% if multiple_of %}, multipleOf: {{multiple_of}}{% end %}{% if minimum %}, minimum: {{minimum}}{% end %}{% if exclusive_minimum %}, exclusiveMinimum: {{exclusive_minimum}}{% end %}{% if maximum %}, maximum: {{maximum}}{% end %}{% if exclusive_maximum %}, exclusiveMaximum: {{exclusive_maximum}}{% end %} }
141+
{ type: {{type_override || "integer"}}, format: {{format_hint || klass.stringify}}{% if multiple_of %}, multipleOf: {{multiple_of}}{% end %}{% if minimum %}, minimum: {{minimum}}{% end %}{% if exclusive_minimum %}, exclusiveMinimum: {{exclusive_minimum}}{% end %}{% if maximum %}, maximum: {{maximum}}{% end %}{% if exclusive_maximum %}, exclusiveMaximum: {{exclusive_maximum}}{% end %}{% if description %}, description: {{description}}{% end %} }
141142
{% elsif klass <= Float %}
142-
{ type: {{type_override || "number"}}, format: {{format_hint || klass.stringify}}{% if multiple_of %}, multipleOf: {{multiple_of}}{% end %}{% if minimum %}, minimum: {{minimum}}{% end %}{% if exclusive_minimum %}, exclusiveMinimum: {{exclusive_minimum}}{% end %}{% if maximum %}, maximum: {{maximum}}{% end %}{% if exclusive_maximum %}, exclusiveMaximum: {{exclusive_maximum}}{% end %} }
143+
{ type: {{type_override || "number"}}, format: {{format_hint || klass.stringify}}{% if multiple_of %}, multipleOf: {{multiple_of}}{% end %}{% if minimum %}, minimum: {{minimum}}{% end %}{% if exclusive_minimum %}, exclusiveMinimum: {{exclusive_minimum}}{% end %}{% if maximum %}, maximum: {{maximum}}{% end %}{% if exclusive_maximum %}, exclusiveMaximum: {{exclusive_maximum}}{% end %}{% if description %}, description: {{description}}{% end %} }
143144
{% end %}
144145
{% elsif klass <= Nil %}
145-
{ type: {{type_override || "null"}}{% if format_hint %}, format: {{format_hint}}{% end %} }
146+
{ type: {{type_override || "null"}}{% if format_hint %}, format: {{format_hint}}{% end %}{% if description %}, description: {{description}}{% end %} }
146147
{% elsif klass <= Time %}
147-
{ type: {{type_override || "string"}}, format: {{format_hint || "date-time"}}{% if pattern %}, pattern: {{pattern}}{% end %} }
148+
{ type: {{type_override || "string"}}, format: {{format_hint || "date-time"}}{% if pattern %}, pattern: {{pattern}}{% end %}{% if description %}, description: {{description}}{% end %} }
148149
{% elsif klass <= UUID %}
149-
{ type: {{type_override || "string"}}, format: {{format_hint || "uuid"}}{% if pattern %}, pattern: {{pattern}}{% end %} }
150+
{ type: {{type_override || "string"}}, format: {{format_hint || "uuid"}}{% if pattern %}, pattern: {{pattern}}{% end %}{% if description %}, description: {{description}}{% end %} }
150151
{% elsif klass <= Hash %}
151152
{% if klass.type_vars.size == 2 %}
152153
{ type: "object", additionalProperties: ::JSON::Schema.introspect({{klass.type_vars[1]}}, nil, {{openapi}}) }
153154
{% else %}
154155
# As inheritance might include the type_vars it's hard to work them out
155156
%klass = {{klass.ancestors[0]}}
156-
%klass.responds_to?(:json_schema) ? %klass.json_schema({{openapi}}) : { type: "object" }
157+
%klass.responds_to?(:json_schema) ? %klass.json_schema({{openapi}}) : { type: "object"{% if description %}, description: {{description}}{% end %} }
157158
{% end %}
158159
{% elsif klass.ancestors.includes? JSON::Serializable %}
159160
{{klass}}.json_schema({{openapi}})
@@ -163,7 +164,7 @@ module JSON
163164
%klass.json_schema({{openapi}})
164165
else
165166
# anything will validate (JSON::Any)
166-
{ type: "object" }
167+
{ type: "object"{% if description %}, description: {{description}}{% end %} }
167168
end
168169
{% end %}
169170
{% end %}

0 commit comments

Comments
 (0)