Home / Blog / JSON tools

JSON tools

Formik with JSON Schema: Adapt Validation Errors Deliberately

Connect JSON Schema validation to Formik through validate, map field errors explicitly, and test string inputs, required fields and submit behavior.

Use the integration that matches your validator

Formik can manage a form whose values are checked by a JSON Schema validator, but a raw JSON Schema object is not automatically a Yup schema. Formik's documented validationSchema integration is designed for Yup-style schemas. For an Ajv-based contract, use a form-level validate function and translate the validator's result into the error object your form expects.

The Formik validation guide describes both approaches. Choose one clear validation path so two competing systems do not produce contradictory messages for the same field. Server-side validation still needs to enforce the request contract because browser validation can be bypassed.

Decide what the form values represent

For this small example, the form contains a name and a seats field. Both are strings while the user edits them. Name must contain at least one character, and seats must be one digit from one through eight. This avoids hidden numeric coercion and keeps the empty input state easy to test.

const schema = {
  type: "object",
  properties: {
    name: {type: "string", minLength: 1},
    seats: {type: "string", pattern: "^[1-8]$"}
  },
  required: ["name", "seats"],
  additionalProperties: false
};

The initial values can be {name: "", seats: ""}. The edited values {name: "Ada", seats: "3"} should pass. The numeric value 3 is intentionally not the same as the editable string "3" in this form contract. If the API expects an integer, construct a separate submission object after successful validation.

Map this flat contract to named field errors

Compile the schema once outside the frequently called validation function. The following adapter targets only this two-field form and the Ajv 8 error shape. It returns user-facing messages through known field names instead of accepting arbitrary path strings as object properties.

const checkValues = ajv.compile(schema);
function validate(values) {
  if (checkValues(values)) return {};
  const errors = {};
  for (const issue of checkValues.errors || []) {
    const field = issue.keyword === "required"
      ? issue.params.missingProperty
      : issue.instancePath === "/name" ? "name"
      : issue.instancePath === "/seats" ? "seats" : null;
    if (field === "name") errors.name = "Enter a name.";
    else if (field === "seats") errors.seats = "Choose 1 to 8 seats.";
  }
  if (!Object.keys(errors).length) errors.name = "Check the form values.";
  return errors;
}

Here ajv is a configured Ajv instance with coercion disabled, and schema is the object above. Pass validate to Formik's validate prop. The adapter deliberately treats an unexpected object-level failure as a visible form problem rather than returning an empty object that would incorrectly imply success.

Test the error mapping separately from the interface

Check the passing values, both empty strings, a missing name, a seats value of "9", and a numeric seats value. The invalid seat cases should produce errors.seats. Then add an unexpected extra property and confirm the adapter still returns a visible error. Reset from an invalid example to the valid example and verify the old messages disappear.

The name rule here accepts whitespace because minLength measures length rather than human usefulness. If the product forbids a whitespace-only name, add an explicit rule or normalization step and a fixture for it. Keep that decision visible instead of claiming the illustrative schema implements every naming policy.

Nested objects and field arrays require a fuller path mapper. Decode JSON Pointer segments correctly and build Formik's expected nested error shape. Do not reuse this flat adapter unchanged for addresses, dynamic rows or keys containing slashes.

Verify submission and accessible feedback

Show each field's error where the user can associate it with the relevant control. Decide when to show messages during editing, blur and submission. Test keyboard submission, correcting an error and adding or removing fields if your real form supports them.

For this exact schema, successful submission can convert seats with Number because the validated string is a single digit from one to eight. Do not apply that assumption to a different schema accepting arbitrary numeric text. Send the server only the intended request fields.

The local JSON Schema Generator From JSON can help draft a starting shape, but it neither creates a Formik form nor supplies the error adapter. Keep the schema, mapping tests and actual form behavior under the application's normal tests as the fields evolve.