Current section

74 Versions

Jump to

Compare versions

5 files changed
+101 additions
-22 deletions
  @@ -2,6 +2,13 @@
2 2
3 3 All notable changes to this project will be documented in this file.
4 4
5 + ## 0.7.1 - 2025-10-12
6 +
7 + ### Added
8 +
9 + - `Zoi.to_json_schema/1` support for metadata (e.g., example, description)
10 + - `guides/quickstart_guide.md` added to the documentation
11 +
5 12 ## 0.7.0 - 2025-10-10
6 13
7 14 ### Added
  @@ -195,6 +195,16 @@ defmodule MyApp.UserSchemaTest do
195 195 end
196 196 ```
197 197
198 + ## Guides
199 +
200 + Check the official guides for more examples and use cases:
201 +
202 + - [Quickstart Guide](https://hexdocs.pm/zoi/quickstart_guide.html)
203 + - [Using Zoi to generate OpenAPI specs](https://hexdocs.pm/zoi/using_zoi_to_generate_openapi_specs.html)
204 + - [Validating controller parameters](https://hexdocs.pm/zoi/validating_controller_parameters.html)
205 + - [Converting Keys From Object](https://hexdocs.pm/zoi/converting_keys_from_object.html)
206 + - [Generating Schemas from JSON](https://hexdocs.pm/zoi/generating_schemas_from_json_example.html)
207 +
198 208 ## Acknowledgements
199 209
200 210 `Zoi` is inspired by [Zod](https://zod.dev/) and [Joi](https://joi.dev/), providing a similar experience for Elixir.
  @@ -2,7 +2,7 @@
2 2 [{<<"Changelog">>,<<"https://hexdocs.pm/zoi/changelog.html">>},
3 3 {<<"GitHub">>,<<"https://github.com/phcurado/zoi">>}]}.
4 4 {<<"name">>,<<"zoi">>}.
5 - {<<"version">>,<<"0.7.0">>}.
5 + {<<"version">>,<<"0.7.1">>}.
6 6 {<<"description">>,
7 7 <<"Zoi is a schema validation library for Elixir, designed to provide a simple and flexible way to define and validate data.">>}.
8 8 {<<"elixir">>,<<"~> 1.14">>}.
  @@ -9,7 +9,7 @@ defmodule Zoi.JSONSchema do
9 9 iex> schema = Zoi.object(%{name: Zoi.string(), age: Zoi.integer()})
10 10 iex> Zoi.to_json_schema(schema)
11 11 %{
12 - "$schema" => "https://json-schema.org/draft/2020-12/schema",
12 + "$schema": "https://json-schema.org/draft/2020-12/schema",
13 13 type: :object,
14 14 properties: %{
15 15 name: %{type: :string},
  @@ -43,6 +43,24 @@ defmodule Zoi.JSONSchema do
43 43 - `Zoi.naive_datetime/0` and `Zoi.ISO.naive_datetime/0`
44 44 - `Zoi.time/0` and `Zoi.ISO.time/0`
45 45
46 + ## Metadata
47 + `Zoi.to_json_schema/1` will attempt to parse metadata defined on types. For more information, check the `Zoi.metadata/1` documentation.
48 + The following metadata will be parsed on JSON Schema conversion:
49 +
50 + - `:description` - Adds a `description` field to the JSON Schema.
51 + - `:example` - Adds an `example` field to the JSON Schema.
52 +
53 + ```elixir
54 + iex> schema = Zoi.string(metadata: [description: "A simple string", example: "Hello, World!"])
55 + iex> Zoi.to_json_schema(schema)
56 + %{
57 + "$schema": "https://json-schema.org/draft/2020-12/schema",
58 + type: :string,
59 + description: "A simple string",
60 + example: "Hello, World!"
61 + }
62 + ```
63 +
46 64 ## Limitations
47 65
48 66 - Complex types or custom types not listed above will raise an error during conversion.
  @@ -72,36 +90,43 @@ defmodule Zoi.JSONSchema do
72 90
73 91 defp encode_schema(%Zoi.Types.String{} = schema) do
74 92 %{type: :string}
93 + |> encode_metadata(schema)
75 94 |> encode_refinements(schema.meta)
76 95 end
77 96
78 97 defp encode_schema(%Zoi.Types.Integer{} = schema) do
79 98 %{type: :integer}
99 + |> encode_metadata(schema)
80 100 |> encode_refinements(schema.meta)
81 101 end
82 102
83 103 defp encode_schema(%Zoi.Types.Float{} = schema) do
84 104 %{type: :number}
105 + |> encode_metadata(schema)
85 106 |> encode_refinements(schema.meta)
86 107 end
87 108
88 109 defp encode_schema(%Zoi.Types.Number{} = schema) do
89 110 %{type: :number}
111 + |> encode_metadata(schema)
90 112 |> encode_refinements(schema.meta)
91 113 end
92 114
93 - defp encode_schema(%Zoi.Types.Boolean{}) do
115 + defp encode_schema(%Zoi.Types.Boolean{} = schema) do
94 116 %{type: :boolean}
117 + |> encode_metadata(schema)
95 118 end
96 119
97 - defp encode_schema(%Zoi.Types.Literal{value: value}) do
120 + defp encode_schema(%Zoi.Types.Literal{value: value} = schema) do
98 121 %{
99 122 const: value
100 123 }
124 + |> encode_metadata(schema)
101 125 end
102 126
103 - defp encode_schema(%Zoi.Types.Null{}) do
127 + defp encode_schema(%Zoi.Types.Null{} = schema) do
104 128 %{type: :null}
129 + |> encode_metadata(schema)
105 130 end
106 131
107 132 defp encode_schema(%Zoi.Types.Array{inner: inner} = schema) do
  @@ -110,6 +135,7 @@ defmodule Zoi.JSONSchema do
110 135 %{
111 136 type: :array
112 137 }
138 + |> encode_metadata(schema)
113 139 |> encode_refinements(schema.meta)
114 140
115 141 _inner ->
  @@ -117,6 +143,7 @@ defmodule Zoi.JSONSchema do
117 143 type: :array,
118 144 items: encode_schema(inner)
119 145 }
146 + |> encode_metadata(schema)
120 147 |> encode_refinements(schema.meta)
121 148 end
122 149 end
  @@ -126,6 +153,7 @@ defmodule Zoi.JSONSchema do
126 153 type: :array,
127 154 prefixItems: Enum.map(schema.fields, &encode_schema/1)
128 155 }
156 + |> encode_metadata(schema)
129 157 |> encode_refinements(schema.meta)
130 158 end
131 159
  @@ -134,12 +162,14 @@ defmodule Zoi.JSONSchema do
134 162 type: :string,
135 163 enum: Enum.map(schema.values, fn {_k, v} -> v end)
136 164 }
165 + |> encode_metadata(schema)
137 166 end
138 167
139 - defp encode_schema(%Zoi.Types.Map{}) do
168 + defp encode_schema(%Zoi.Types.Map{} = schema) do
140 169 %{
141 170 type: :object
142 171 }
172 + |> encode_metadata(schema)
143 173 end
144 174
145 175 defp encode_schema(%Zoi.Types.Object{} = schema) do
  @@ -154,50 +184,61 @@ defmodule Zoi.JSONSchema do
154 184 |> Enum.map(fn {k, _v} -> k end),
155 185 additionalProperties: false
156 186 }
187 + |> encode_metadata(schema)
157 188 end
158 189
159 - defp encode_schema(%Zoi.Types.Intersection{schemas: schemas}) do
190 + defp encode_schema(%Zoi.Types.Intersection{schemas: schemas} = schema) do
160 191 %{
161 192 allOf: Enum.map(schemas, &encode_schema/1)
162 193 }
194 + |> encode_metadata(schema)
163 195 end
164 196
165 - defp encode_schema(%Zoi.Types.Union{schemas: schemas}) do
197 + defp encode_schema(%Zoi.Types.Union{schemas: schemas} = schema) do
166 198 %{
167 199 anyOf: Enum.map(schemas, &encode_schema/1)
168 200 }
201 + |> encode_metadata(schema)
169 202 end
170 203
171 - defp encode_schema(%Zoi.Types.Date{}) do
204 + defp encode_schema(%Zoi.Types.Date{} = schema) do
172 205 %{type: :string, format: :date}
206 + |> encode_metadata(schema)
173 207 end
174 208
175 - defp encode_schema(%Zoi.ISO.Date{}) do
209 + defp encode_schema(%Zoi.ISO.Date{} = schema) do
176 210 %{type: :string, format: :date}
211 + |> encode_metadata(schema)
177 212 end
178 213
179 - defp encode_schema(%Zoi.Types.DateTime{}) do
214 + defp encode_schema(%Zoi.Types.DateTime{} = schema) do
180 215 %{type: :string, format: :"date-time"}
216 + |> encode_metadata(schema)
181 217 end
182 218
183 - defp encode_schema(%Zoi.ISO.DateTime{}) do
219 + defp encode_schema(%Zoi.ISO.DateTime{} = schema) do
184 220 %{type: :string, format: :"date-time"}
221 + |> encode_metadata(schema)
185 222 end
186 223
187 - defp encode_schema(%Zoi.Types.NaiveDateTime{}) do
224 + defp encode_schema(%Zoi.Types.NaiveDateTime{} = schema) do
188 225 %{type: :string, format: :"date-time"}
226 + |> encode_metadata(schema)
189 227 end
190 228
191 - defp encode_schema(%Zoi.ISO.NaiveDateTime{}) do
229 + defp encode_schema(%Zoi.ISO.NaiveDateTime{} = schema) do
192 230 %{type: :string, format: :"date-time"}
231 + |> encode_metadata(schema)
193 232 end
194 233
195 - defp encode_schema(%Zoi.Types.Time{}) do
234 + defp encode_schema(%Zoi.Types.Time{} = schema) do
196 235 %{type: :string, format: :time}
236 + |> encode_metadata(schema)
197 237 end
198 238
199 - defp encode_schema(%Zoi.ISO.Time{}) do
239 + defp encode_schema(%Zoi.ISO.Time{} = schema) do
200 240 %{type: :string, format: :time}
241 + |> encode_metadata(schema)
201 242 end
202 243
203 244 defp encode_schema(schema) do
  @@ -337,4 +378,17 @@ defmodule Zoi.JSONSchema do
337 378 # json_schema
338 379 end
339 380 end
381 +
382 + defp encode_metadata(json_schema, zoi_schema) do
383 + Enum.reduce(Zoi.metadata(zoi_schema), json_schema, fn
384 + {:description, description}, acc ->
385 + Map.put(acc, :description, description)
386 +
387 + {:example, example}, acc ->
388 + Map.put(acc, :example, example)
389 +
390 + _, acc ->
391 + acc
392 + end)
393 + end
340 394 end
  @@ -2,7 +2,7 @@ defmodule Zoi.MixProject do
2 2 use Mix.Project
3 3
4 4 @source_url "https://github.com/phcurado/zoi"
5 - @version "0.7.0"
5 + @version "0.7.1"
6 6
7 7 def project do
8 8 [
  @@ -65,11 +65,12 @@ defmodule Zoi.MixProject do
65 65
66 66 defp docs do
67 67 [
68 - main: "Zoi",
68 + main: "readme",
69 69 source_ref: "v#{@version}",
70 70 logo: "guides/images/logo.png",
71 71 extra_section: "GUIDES",
72 72 source_url: @source_url,
73 + groups_for_extras: groups_for_extras(),
73 74 skip_undefined_reference_warnings_on: ["CHANGELOG.md"],
74 75 extras: extras()
75 76 ]
  @@ -77,12 +78,19 @@ defmodule Zoi.MixProject do
77 78
78 79 defp extras do
79 80 [
80 - "README.md",
81 81 "CHANGELOG.md",
82 - "guides/converting_keys_from_object.md",
83 - "guides/generating_schemas_from_json_example.md",
82 + "README.md",
83 + "guides/quickstart_guide.md",
84 84 "guides/using_zoi_to_generate_openapi_specs.md",
85 - "guides/validating_controller_parameters.md"
85 + "guides/validating_controller_parameters.md",
86 + "guides/converting_keys_from_object.md",
87 + "guides/generating_schemas_from_json_example.md"
88 + ]
89 + end
90 +
91 + defp groups_for_extras do
92 + [
93 + Guides: ~r/guides\/.*\.md/
86 94 ]
87 95 end
88 96 end