Skip to main content
{/}codefunc
GuidesJuly 14, 2026 · 6 min read

JSON Schema Validation: Contracts, Required Fields, and API Mistakes to Avoid

Learn JSON Schema basics — types, required properties, common API contract errors — and how to validate payloads in the browser before you commit or deploy.

By codefunc

json-schemavalidationapicontractsjson

Valid JSON is not the same as correct JSON. {"price": "9.99"} parses fine and still breaks billing. JSON Schema gives APIs and config files a shared contract: which fields exist, which types they use, and what "required" means under versioning pressure. Teams that only run syntax checks discover shape bugs in production; teams that validate schema in CI and during local review catch them at the PR boundary.

Bottom line: Use JSON Schema to enforce shape, not just parseability. Declare type, required, and additionalProperties deliberately. Validate sample payloads with a schema validator before merge — syntax-only tools will not save you from wrong types.

Who this guide is for

API authors, frontend consumers of those APIs, and anyone maintaining JSON config (CI, feature flags, CMS exports). If you already format and syntax-check JSON, this is the next layer.

Schema basics

A JSON Schema is a JSON document describing other JSON documents. Minimal example:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/schemas/order.json",
  "type": "object",
  "required": ["id", "items"],
  "properties": {
    "id": { "type": "string", "minLength": 1 },
    "items": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": ["sku", "quantity"],
        "properties": {
          "sku": { "type": "string" },
          "quantity": { "type": "integer", "minimum": 1 }
        },
        "additionalProperties": false
      }
    },
    "note": { "type": "string" }
  },
  "additionalProperties": false
}
Keyword Role
type object, array, string, number, integer, boolean, null
properties Declares object fields
required Lists keys that must be present
items Schema for array elements
enum / const Closed sets of values
additionalProperties Whether unknown keys are allowed
$ref Reuse definitions

Draft versions (draft-07, 2019-09, 2020-12) differ slightly. Pin $schema and use a validator that matches.

Syntax validation vs schema validation

Check Question Tool
Syntax Is this parseable JSON? JSON validator
Formatting Can humans read it? JSON formatter
Schema Does it match the contract? JSON Schema validator

Workflow for a failing webhook:

  1. Format the payload with the JSON formatter so line numbers make sense.
  2. Confirm syntax with the JSON validator.
  3. Run the payload against your schema in the JSON Schema validator.
  4. Fix type/required errors before retrying the provider.

Required fields and presence vs null

In JSON Schema, required means the key must exist. It does not automatically forbid null unless you say so.

{
  "type": "object",
  "required": ["email"],
  "properties": {
    "email": { "type": "string" }
  }
}
Instance Result
{} Fail — missing email
{"email": null} Fail — wrong type
{"email": "a@b.co"} Pass

If your API uses null to clear a field, allow it explicitly:

"email": { "type": ["string", "null"] }

Document the difference between omitted, null, and "" — consumers will otherwise guess wrong.

Types that cause API contract mistakes

Numbers vs strings

JSON has no decimal type distinct from number. Still, APIs often send money as strings to preserve precision:

{ "amount": "19.99", "currency": "USD" }

If the schema says "type": "number", string amounts fail validation — correctly. Align schema with serialization policy; do not weaken the schema to match a buggy client without a version bump.

Integers vs numbers

"type": "integer" rejects 1.5. JavaScript consumers that JSON-parse everything as number still need server-side integer checks for IDs and counts.

Booleans vs truthy strings

"type": "boolean" rejects "true". Query strings and form posts often need a separate coercion layer before schema validation of JSON bodies.

Arrays that should be objects

{ "roles": { "0": "admin", "1": "editor" } }

This is an object, not an array. Schemas with "type": "array" catch the mistake; open-ended {} typing in TypeScript sometimes does not.

additionalProperties and evolving APIs

Setting Effect
omitted / true Unknown keys allowed
false Unknown keys rejected
schema object Unknown keys must match that schema

Strict APIs benefit from "additionalProperties": false on request bodies so typos ("emial") fail loudly. Response schemas are often looser so additive fields do not break old clients — or you version responses explicitly.

Additive change (usually safe for responses): new optional property.

Breaking changes: removing a field, tightening types, making a new field required on requests without a version bump.

Common API contract mistakes

  1. Schema drifts from code — OpenAPI/JSON Schema generated once, then hand-edited handlers. Generate or test both in CI.
  2. Required on response fields that are conditionally absent — empty states fail validation in contract tests.
  3. Using number for IDs larger than 2^53-1 — use strings for snowflakes / uint64 IDs.
  4. Forgetting minItems — empty items: [] passes until checkout logic explodes.
  5. Overusing oneOf without clear errors — validators report opaque mismatches; prefer simpler unions.
  6. Validating only in the happy-path test — include fixtures for nulls, extras, and wrong types.
  7. Trusting client-side validation alone — browsers can be bypassed; schema-check again on the server.

Validate before you commit

Local loop:

# Example: ajv-cli in a repo
npx ajv validate -s schemas/order.json -d fixtures/order.ok.json
npx ajv validate -s schemas/order.json -d fixtures/order.bad-type.json

PR checklist:

  1. Pretty-print fixtures with the JSON formatter for readable diffs.
  2. Ensure fixtures are syntactically valid via JSON validator.
  3. Run positive and negative cases through JSON Schema validator (or CI equivalent).
  4. Reject PRs that change handlers without updating schema and fixtures.

Browser validators are ideal for quick vendor payload checks and for reviewing a schema change without installing tooling — especially on locked-down machines. Keep production customer data out of any tool you do not trust; codefunc schema tools run client-side in your browser.

Designing schemas teams will keep

  • One schema file (or $id) per resource version
  • Shared $defs for money, addresses, pagination
  • Examples in the schema or adjacent fixtures/ directory
  • Contract tests that fail the build on mismatch
  • Human-readable description fields on non-obvious properties

Example pagination fragment:

{
  "type": "object",
  "required": ["items", "nextCursor"],
  "properties": {
    "items": { "type": "array" },
    "nextCursor": { "type": ["string", "null"] }
  },
  "additionalProperties": false
}

Practical takeaway

Syntax validation answers "can we parse this?" Schema validation answers "is this the resource we agreed on?" Put type, required, and additionalProperties decisions in versioned schema files, test them with good and bad fixtures, and run the JSON Schema validator before merging contract changes. Keep JSON formatter and JSON validator in the loop for readability and parse errors — then let the schema catch the rest.

Sources

Try it on codefunc

Related articles

3

Search tools

Find a developer tool