skip to content

In a Postman test script, what does pm.response.to.have.jsonSchema(schema) assert, and what parses the body?

level: middleimportance: must knowfreq 58%

answer

  1. One call instead of field-by-field checks
  2. The validator is not Postman's own code
  3. Off the response chain, parsing is free
  4. A second argument names the validator's options

basics

~10 s

Postman's jsonSchema assertion validates a value against a JSON Schema object using Ajv. Chained off pm.response it parses the reply body first; chained off pm.expect it validates whatever value you handed in.

solid answer

~40 s

`jsonSchema` is a chai assertion the Postman sandbox registers, backed by **Ajv** — the sandbox injects the Ajv constructor into its chai plugin at startup. It reads two ways: `pm.response.to.have.jsonSchema(schema)`, where the reply body is parsed automatically before validating, and `pm.expect(value).to.be.jsonSchema(schema)`, where `value` is validated exactly as passed. Both negate, so `pm.response.to.not.have.jsonSchema(schema)` is a real check. A failure reads `expected data to satisfy schema but found following errors:` with one line per Ajv error, such as `data.alpha should be boolean`; the negated failure reads `expected data to not satisfy schema`. The sandbox's type declarations give the signature as `jsonSchema(schema)` and `jsonSchema(schema, ajvOptions)`, so a second object configures the validator rather than Postman.

code

javascript · 13 lines
javascript
const schema = {
    type: 'object',
    properties: {
        id: { type: 'string' },
        total: { type: 'number' }
    }
};

// the response chain parses the body for you
pm.response.to.have.jsonSchema(schema);

// pm.expect validates the value exactly as handed in
pm.expect(pm.response.json()).to.be.jsonSchema(schema);

go deeper

for a junior

Recall the two spellings — pm.response.to.have.jsonSchema(schema) and pm.expect(value).to.be.jsonSchema(schema) — and that the first one parses the reply body for you while the second takes the value as given.

for a middle

Explain that the assertion is a chai plugin backed by Ajv, that the sandbox injects the Ajv constructor, and that the second declared parameter is an options object for that validator rather than a Postman setting.

for a senior

Show you read the failure text in a run report and act on it: one line per validation error under a 'satisfy schema' message, with 'data' meaning the value under test. Say what a green result does not prove.

for a principal

Own the boundary. Decide where a runtime shape assertion belongs in a suite versus a contract or specification-diff gate, and set the expectation that a schema copy living in a script is a fixture with an owner.

## The assertion and the engine behind it `jsonSchema` is a **chai assertion** that the Postman sandbox registers when it builds a script context. At initialisation the sandbox calls `chai.use(require('chai-postman')(sdk, _, Ajv))` — it *injects* the **Ajv** constructor into the plugin. Every `jsonSchema` call in a test script is therefore an Ajv validation wearing a chai face. That attribution matters in an interview: the keyword vocabulary a schema may use, the strictness applied to it, and the wording of each individual error are **Ajv's**, not Postman's. Postman contributes the chain, the auto-parse and the surrounding assertion message. The sandbox's own type declarations list two overloads under the `have` chain: ```javascript pm.response.to.have.jsonSchema(schema); pm.response.to.have.jsonSchema(schema, ajvOptions); ``` ## Two chains, and who does the parsing The same assertion is reachable two ways, and the difference between them is entirely about who turns bytes into an object. | Written as | Value validated | Who parses the JSON | |---|---|---| | `pm.response.to.have.jsonSchema(s)` | the reply body | the assertion, automatically | | `pm.expect(v).to.be.jsonSchema(s)` | `v`, exactly as handed in | you, before the call | `pm.expect` is chai's `expect`, so the second form accepts any value — a slice of a payload, an object you assembled, a value you already parsed with `pm.response.json()`. The first form is the convenience: hand it a schema and nothing else, and it takes the response, parses the body, and validates the resulting object. That auto-parse is the most useful thing about the response chain and the most common source of confusion: hand the assertion the **raw text** of a body instead and you are validating a string, so a schema describing an object simply fails. ## What one call covers - every field the schema names, at every depth, in one line; - a document you can review, diff and reuse across several requests; - new fields in the payload without a new assertion line; - a failure that names the offending path rather than a bare value mismatch. ## Negation and the failure text Both chains negate, and the negated form is a real assertion rather than a no-op: - `pm.response.to.not.have.jsonSchema(s)` passes when the parsed body does **not** satisfy `s`; - `pm.expect(v).to.not.be.jsonSchema(s)` is the same for an arbitrary value. The failure text is worth recognising in a run report: 1. a failed positive assertion reads `expected data to satisfy schema but found following errors:`, followed by one line per validation error — for example `data.alpha should be boolean`; 2. a failed negated assertion reads `expected data to not satisfy schema`, with no error list, because there were none to list. The word `data` in those messages is the validator's own name for the value under test. It is not a field in your payload, and candidates who read it as one usually go looking for a `data` wrapper that was never there. ## The second argument The declared second parameter is named `ajvOptions`. It is an options object for the validator sitting behind the assertion, which is the practical summary of the whole feature: when you tune this assertion you are tuning **Ajv**, not tuning Postman. Two consequences follow: 1. behaviour you already know from Ajv is the behaviour you get here — there is no Postman-specific dialect layered on top of it; 2. if two assertions in one script need different validator behaviour, each call carries its own options object; there is no collection-level place to set them once for the whole run. ## What a pass does and does not mean A green `jsonSchema` assertion means one thing precisely: **the value under test satisfied the schema object the script passed in, as judged by Ajv.** Everything else is inference, and each of these is a claim it does not make: - it is not a check against any published definition — the schema is a JavaScript object living in the script; - it does not assert that values are *correct*, only that they are shaped as the schema describes; - it has no opinion about anything the schema does not mention, so silence is not a failure; - it does not compare this release's shape against the previous one; a breaking-change gate over a published specification is a different tool's job. Against a hand-written per-field assertion set, the schema assertion buys breadth for one line, in a form somebody else can read. Against contract tooling, it buys nothing at all about *agreement between two parties*: it is a runtime shape check of one reply, in one run, against one document you happened to be holding. Saying which of those you are doing is the part of the answer that lands.

  • What is the second argument in jsonSchema(schema, ajvOptions), and who consumes it?
    It is an options object for the validator behind the assertion — the sandbox's own type declarations name the parameter `ajvOptions`. Tuning it tunes Ajv, not Postman, and it is per call: there is no collection-level place to set validator behaviour once for a whole run.
  • What happens if you hand the assertion the raw text of a body rather than the parsed object?
    It validates the string. `pm.response.to.have.jsonSchema(s)` parses for you, but `pm.expect(pm.response.text()).to.be.jsonSchema(s)` passes a string through untouched, so a schema describing an object fails against it. Parse first, or use the response chain.
  • What does the word 'data' mean in the failure message 'data.alpha should be boolean'?
    It is the validator's name for the value under test, not a field in the payload. The path after it — `.alpha` — is real and points at the offending property, but there is no `data` wrapper in the reply to go looking for.

saying these in an interview costs you the question

  • Thinks Postman ships its own hand-written schema validator
  • Passes pm.response.text() and expects the string to validate
  • Believes the schema is read out of the collection file automatically
  • Assumes a green schema check also verifies field values
  • Writes tv4.validate in new scripts as though it were current
  • Calls the negated form a no-op that can never fail