Skip to content

Commit 806e55c

Browse files
authored
Document validation response handling with fetchHydra (#2263)
1 parent d6dd6c4 commit 806e55c

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

admin/validation.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,109 @@ If you submit the form with an invalid ISBN, you will see:
6666

6767
![Submission error field](images/submission-error-field.png)
6868

69+
### How Server-side Validation Works Under the Hood
70+
71+
When `fetchHydra` receives an error response (HTTP status outside the 2xx range), it
72+
[expands](https://www.w3.org/TR/json-ld11-api/#expansion) the JSON-LD body using the API
73+
documentation context. This means the error object passed to `getSubmissionErrors` does not contain
74+
the raw response payload, but an expanded JSON-LD document.
75+
76+
For example, a typical API Platform validation error response:
77+
78+
```json
79+
{
80+
"@context": "/contexts/ConstraintViolationList",
81+
"@type": "ConstraintViolationList",
82+
"title": "An error occurred",
83+
"description": "isbn: This value is neither a valid ISBN-10 nor a valid ISBN-13.",
84+
"violations": [
85+
{
86+
"propertyPath": "isbn",
87+
"message": "This value is neither a valid ISBN-10 nor a valid ISBN-13."
88+
}
89+
]
90+
}
91+
```
92+
93+
Gets expanded into a structure like:
94+
95+
```json
96+
[
97+
{
98+
"http://www.w3.org/ns/hydra/core#description": [
99+
{
100+
"@value": "isbn: This value is neither a valid ISBN-10 nor a valid ISBN-13."
101+
}
102+
],
103+
"http://www.w3.org/ns/hydra/core#violations": [
104+
{
105+
"http://www.w3.org/ns/hydra/core#propertyPath": [{ "@value": "isbn" }],
106+
"http://www.w3.org/ns/hydra/core#ConstraintViolation/message": [
107+
{
108+
"@value": "This value is neither a valid ISBN-10 nor a valid ISBN-13."
109+
}
110+
]
111+
}
112+
]
113+
}
114+
]
115+
```
116+
117+
This expanded document is what the `HttpError`'s `body` property contains. The `getSubmissionErrors`
118+
method of the [schema analyzer](components.md#hydra-schema-analyzer) handles parsing this expanded
119+
format automatically and maps violations back to field names.
120+
121+
### Handling Validation Errors Outside React Admin
122+
123+
If you use `fetchHydra` in a custom React application (outside of React Admin forms), you need to
124+
handle the expanded JSON-LD error format yourself.
125+
126+
Here is an example of how to extract validation errors from the expanded response:
127+
128+
```typescript
129+
import { fetchHydra } from "@api-platform/admin";
130+
import type { HttpError } from "react-admin";
131+
132+
async function submitData(url: URL, data: object) {
133+
try {
134+
return await fetchHydra(url, {
135+
method: "POST",
136+
body: JSON.stringify(data),
137+
});
138+
} catch (error) {
139+
if (error instanceof HttpError && error.status === 422 && error.body?.[0]) {
140+
const content = error.body[0];
141+
// Find the violations key (e.g. "http://www.w3.org/ns/hydra/core#violations")
142+
const violationKey = Object.keys(content).find((key) => key.includes("violations"));
143+
if (violationKey) {
144+
const base = violationKey.substring(0, violationKey.indexOf("#"));
145+
const violations = content[violationKey].map((violation) => ({
146+
propertyPath: violation[`${base}#propertyPath`]?.[0]?.["@value"],
147+
message: (violation[`${base}#message`] ??
148+
violation[`${base}#ConstraintViolation/message`])?.[0]?.["@value"],
149+
}));
150+
return { violations };
151+
}
152+
}
153+
throw error;
154+
}
155+
}
156+
```
157+
158+
Alternatively, you can use the
159+
[`jsonld.compact`](https://github.com/digitalbazaar/jsonld.js#compacting) method to convert the
160+
expanded response back to a compact form closer to the original payload:
161+
162+
```typescript
163+
import jsonld from "jsonld";
164+
165+
// Inside your catch block, after getting error.body:
166+
const compacted = await jsonld.compact(error.body, {
167+
"@context": "http://www.w3.org/ns/hydra/context.jsonld",
168+
});
169+
// compacted now has a structure closer to the original API response
170+
```
171+
69172
## Validation With React Admin Inputs
70173

71174
If you replace an `<InputGuesser>` with a React Admin

0 commit comments

Comments
 (0)