Skip to content

Commit cb725ad

Browse files
committed
updated readme file
1 parent 721b561 commit cb725ad

File tree

5 files changed

+419
-2
lines changed

5 files changed

+419
-2
lines changed

README.md

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,153 @@ const friendlyErrors = await betterJsonSchemaErrors(result, schemaUri, instance,
122122

123123
### 4. Handling `anyOf` with Clarity
124124

125-
The `anyOf` keyword is a powerful but complex JSON Schema feature. **Better-JSON-Schema-Errors** intelligently simplifies its output by providing clear, consolidated error messages that are easier to debug. For detailed examples, see the dedicated [**anyOf** documentation](./docs/anyOf.md).
125+
The `anyOf` keyword is a powerful but complex JSON Schema feature. **Better-JSON-Schema-Errors** intelligently simplifies its output by providing clear, consolidated error messages that are easier to debug.
126126

127+
**Schema:**
128+
```json
129+
{
130+
"anyOf": [
131+
{ "type": "string" },
132+
{ "type": "number" }
133+
]
134+
}
135+
```
136+
137+
Invalid Instance:-
138+
``` Json
139+
false
140+
```
141+
BetterJSONSchemaErrors Output:-
142+
``` Json
143+
{
144+
"errors": [
145+
{
146+
"schemaLocation": "https://example.com/main#/anyOf",
147+
"instanceLocation": "#",
148+
"message": "The instance should be of type 'string' or 'number' but found 'boolean'."
149+
}
150+
]
151+
}
152+
```
153+
154+
For detailed examples, see the dedicated [**anyOf** documentation](./documentation/anyOf.md).
155+
156+
### 5. Handling `enum` with Suggestions
157+
158+
When data doesn’t match an allowed `enum` value, Better JSON Schema Errors produces clear messages.
159+
It can also suggest the closest valid value (using string similarity).
160+
161+
Example:
162+
163+
```json
164+
{
165+
"errors": [
166+
{
167+
"message": "Unexpected value 'appl'. Did you mean 'apple'?",
168+
"instanceLocation": "#/fruit",
169+
"schemaLocation": "https://example.com/main#/properties/fruit/enum"
170+
}
171+
]
172+
}
173+
```
174+
This makes typos or near-misses much easier to debug.
175+
For full details and strategies, see the dedicated [enum documentation](./documentation/enum.md).
176+
177+
### 6. Range constraint keyword
178+
Better JSON Schema Errors consolidates multiple range-related validation errors (`minimum`, `maxLength`, `minItems`, etc.) into a single, clear message.
179+
For example, a schema like:
180+
```json
181+
{ "allOf": [
182+
{ "minimum": 3 },
183+
{ "minimum": 5 }
184+
]
185+
}
186+
```
187+
Instance:-
188+
```Json
189+
2
190+
```
191+
BetterJSONSchemaErrors Output:-
192+
``` Json
193+
{
194+
"errors": [
195+
{
196+
"schemaLocation": "https://example.com/main#/allOf/1/minimum",
197+
"instanceLocation": "#",
198+
"message": "Expected a number greater than 5."
199+
}
200+
]
201+
}
202+
```
203+
Instead of 2 error message it manage to give single concise error message. For details, see the dedicated [Range documenetation](./documentation/range-handler.md)
204+
205+
### 6. Custom Keywords and Error Handlers
206+
In order to create the custom keywords and error handlers we need create and register two types of handler: **Normalization Handler** and **Error Handlers**
207+
208+
1. Normalization: This phase takes the raw, often deeply nested, error tree from the validator and converts it into a NormalizedOutput (can check type of normalizedOutput in the index.d.ts file).
209+
210+
2. Error Handling: This phase takes the normalized data and uses it to generate the final error messages. This is the job of the Error Handlers.
211+
212+
Fist step -: Creating the keywordHandler
213+
```Js
214+
/**
215+
* @import { KeywordHandler } from "@hyperjump/better-json-schema-errors"
216+
*/
217+
218+
/** @type KeywordHandler */
219+
const multipleOfTen = {
220+
appliesTo(type) {
221+
return type === "number"
222+
}
223+
};
224+
225+
export default multipleOfTen;
226+
227+
```
228+
229+
Second step -: Creating the errorHandler
230+
```Js
231+
import { getSchema } from "@hyperjump/json-schema/experimental";
232+
import * as Schema from "@hyperjump/browser";
233+
import * as Instance from "@hyperjump/json-schema/instance/experimental";
234+
235+
/**
236+
* @import { ErrorHandler, ErrorObject } from "@hyperjump/better-json-schema-errors"
237+
*/
238+
239+
/** @type ErrorHandler */
240+
const ErrorHandler = async (normalizedErrors, instance, localization) => {
241+
/** @type ErrorObject[] */
242+
const errors = [];
243+
244+
if (normalizedErrors["https://json-schema.org/keyword/multipleOfTen"]) {
245+
for (const schemaLocation in normalizedErrors["https://json-schema.org/keyword/multipleOfTen"]) {
246+
if (!normalizedErrors["https://json-schema.org/keyword/multipleOfTen"][schemaLocation]) {
247+
errors.push({
248+
message: "Instance must be multiple of 10",
249+
instanceLocation: Instance.uri(instance),
250+
schemaLocation: schemaLocation
251+
});
252+
}
253+
}
254+
}
255+
256+
return errors;
257+
};
258+
259+
260+
```
261+
262+
Step 3:- Register the handlers:
263+
264+
```Js
265+
import { setNormalizationHandler, addErrorHandler } from "@hyperjump/better-json-schema-errors";
266+
const KEYWORD_URI = "https://example.com/keyword/multipleOfTen";
267+
268+
setNormalizationHandler(CUSTOM_KEYWORD_URI, multipleOften);
269+
270+
addErrorHandler(errorHandler);
271+
```
127272
## API
128273

129274
<https://better-json-schema-errors.hyperjump.io/modules.html>

documentation/anyOf.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,72 @@ BetterJSONSchemaErrors Output:-
116116
}
117117
]
118118
}
119+
```
120+
121+
#### 4. anyOf handling const/enum
122+
123+
When an instance fails all enum or const options in an anyOf, the library merges them into one clear error message, avoiding multiple errors and even suggesting close matches in many cases.
124+
125+
**Schema:**
126+
```json
127+
{
128+
"anyOf": [
129+
{ "enum": ["a", "b", "c"] },
130+
{ "const": 1 }
131+
]
132+
}
133+
```
134+
135+
Invalid Instance:-
136+
``` Json
137+
2
138+
```
139+
BetterJSONSchemaErrors Output:-
140+
``` Json
141+
{
142+
"errors": [
143+
{
144+
"schemaLocation": "https://example.com/main#/anyOf",
145+
"instanceLocation": "#",
146+
"message": "Unexpected value 2. Expected one of: 'a', 'b', 'c' or 1 ."
147+
}
148+
]
149+
}
150+
151+
```
152+
153+
#### 5. anyOf with a Discriminator
154+
155+
When `anyOf` uses a discriminator, the library leverages it to give precise errors, matching the instance to the intended alternative via a specific property (e.g., `"type"`, `"const"`).
156+
157+
158+
**Schema:**
159+
```json
160+
{
161+
"anyOf": [
162+
{ "properties": { "type": { "const": "a" }, "apple": { "type": "string" } } },
163+
{ "properties": { "type": { "const": "b" }, "banana": { "type": "string" } } }
164+
]
165+
}
166+
```
167+
168+
Invalid Instance:-
169+
``` Json
170+
{
171+
"type": "a",
172+
"apple": 42
173+
}
174+
```
175+
BetterJSONSchemaErrors Output:-
176+
``` Json
177+
{
178+
"errors": [
179+
{
180+
"schemaLocation": "https://example.com/main#/anyOf/0/properties/apple/type",
181+
"instanceLocation": "#/apple",
182+
"message": "The instance should be of type 'string' but found 'number'."
183+
}
184+
]
185+
}
186+
119187
```

documentation/enum.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Handling `enum` in Better JSON Schema Errors
2+
3+
The `enum` keyword restricts a value to a fixed set of allowed options.
4+
This library enhances `enum` errors with **two strategies**:
5+
6+
---
7+
8+
## 1. Suggestion Strategy (Levenshtein Distance)
9+
10+
If the user-provided value is close to one of the allowed values (based on string similarity),
11+
the error message will include a **suggestion**.
12+
13+
Example Schema:
14+
**Schema:**
15+
```json
16+
{
17+
"type": "string",
18+
"enum": ["apple", "banana", "orange"]
19+
}
20+
```
21+
22+
Invalid Instance:-
23+
``` Json
24+
{ "fruit": "appl" }
25+
```
26+
BetterJSONSchemaErrors Output:-
27+
``` Json
28+
{
29+
"errros": {
30+
"message": "Unexpected value 'appl'. Did you mean 'apple'?",
31+
"instanceLocation": "#/fruit",
32+
"schemaLocation": "https://example.com/main#/properties/fruit/enum"
33+
}
34+
}
35+
```
36+
## 2. Fallback Strategy (List All Options)
37+
38+
If no close match is found, the error lists all valid values:
39+
40+
Example Schema:
41+
**Schema:**
42+
```json
43+
{
44+
"type": "string",
45+
"enum": ["apple", "banana", "orange"]
46+
}
47+
```
48+
49+
Invalid Instance:-
50+
``` Json
51+
{ "fruit": "grape" }
52+
```
53+
BetterJSONSchemaErrors Output:-
54+
``` Json
55+
{
56+
"errros": {
57+
"message": "Unexpected value 'grape'. Expected one of: 'apple', 'banana', or 'orange'.",
58+
"instanceLocation": "#/fruit",
59+
"schemaLocation": "https://example.com/main#/properties/fruit/enum"
60+
}
61+
}
62+
```

0 commit comments

Comments
 (0)