skip to content

In Apache JMeter, how do you capture an order id from a JSON confirmation body for the next request?

level: juniorimportance: must knowfreq 74%

answer

  1. Structure-aware, not a text search
  2. A post-processor under the sampler
  3. Names, expressions, match number, defaults
  4. Set a default you would actually notice

basics

~20 s

Add a JSON Extractor as a child of the sampler that returns the confirmation body, give it a variable name and a JSON Path expression, then reference the captured value as ${orderId} in the next request.

solid answer

~50 s

Apache JMeter 6.0.0 ships a **JSON Extractor** post-processor (`JSONPostProcessor` in the saved `.jmx`). Place it as a child of the sampler whose response carries the confirmation body, so it runs against that sample. Fill **Names of created variables** with `orderId`, **JSON Path expressions** with an expression that walks the body down to the id, **Match No. (0 for Random)** with `1` when you expect exactly one id, and **Default Values** with something you would notice, such as `NO_ORDER_ID`. The following sampler then refers to `${orderId}`. Leaving Match No. blank is not the same as `1` — a blank field is read as `0`, which picks a match at random. If the expression finds nothing, the extractor stores the default and sets `orderId_matchNr` to `0`; it does not mark the sample failed, so a recognisable default is what makes the miss visible.

go deeper

for a junior

Recall the element name, that it is a post-processor placed under the sampler, and that the captured value is read back as ${orderId}.

for a middle

Explain what each of the four fields does, especially that a blank Match No. is read as 0 and therefore picks a random match rather than the first one.

for a senior

Show how you make a failed capture visible: a recognisable Default Value, and the knowledge that this element never fails the sample on its own.

for a principal

Weigh where captured state belongs across a plan and who owns the default when several elements write the same variable name for different steps.

This walkthrough is against Apache JMeter 6.0.0. ## The element you are looking for JMeter's structure-aware reader for JSON bodies is the **JSON Extractor**, a post-processor. In a saved plan it serialises as `<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="...">`. It is not an assertion and not a listener: it runs after the sampler in its scope has returned, reads that sample's response body, and writes JMeter variables that later elements can interpolate. The expression syntax you type into it is a specification of its own; what this element owns is the handful of fields wrapped around that expression. ## The fields, and what each one is called on disk | GUI label | `.jmx` property | Value for one order id | |---|---|---| | Names of created variables | `JSONPostProcessor.referenceNames` | `orderId` | | JSON Path expressions | `JSONPostProcessor.jsonPathExprs` | the expression reaching the id | | Match No. (0 for Random) | `JSONPostProcessor.match_numbers` | `1` | | Default Values | `JSONPostProcessor.defaultValues` | `NO_ORDER_ID` | | Compute concatenation var (suffix _ALL) | `JSONPostProcessor.compute_concat` | unticked | ## Where you put it The extractor is a **child of the sampler** whose response you want. That placement is what decides which sample it reads. Its *Apply to* selector then narrows things further: - **Main sample only** — the sampler's own response. - **Sub-samples only** — only responses generated underneath it. - **Main sample and sub-samples** — both. - **JMeter Variable Name to use** — do not read a response at all; parse the contents of the named variable instead. This is how you re-parse a body you have already stashed. ## What Match No. selects 1. **`1`, or any positive N** — take the Nth match. If N is larger than the number of matches found, the Default Value is stored instead. 2. **`0`** — pick one of the matches at random. This is also what an **empty** Match No. field means, which is the single most common surprise for someone new to the element. 3. **`-1`** — take every match. This does not simply add more variables; it changes *which* variables get written, and the bare `orderId` is not one of them. For a confirmation body carrying exactly one order id, `1` is the honest setting. It says what you expect, and it makes a second unexpected match harmless rather than a coin flip. ## What happens when nothing matches - `orderId` is set to the **Default Value** you supplied. - `orderId_matchNr` is set to `0`. - The sample is **not** marked failed. The JSON Extractor never touches the sample result. - A malformed body or a broken expression is logged as `Error processing JSON content in <element name>`; a clean no-match is not logged as an error at all. That last group is why the Default Value field matters more than it looks. With no default, a failed capture leaves the variable unset and the next request sends the literal text `${orderId}` to the server — which usually comes back as a 400 or a 404 several steps later, far from the element that actually broke. With `NO_ORDER_ID` in the field, the bad request is self-describing the moment you look at it. ## Two limits worth knowing up front - There is **no field-to-check selector** on this element. It reads the response body, or the contents of a variable when *Apply to* is set to a variable name. It cannot read response headers or the URL. - The variable it writes is an ordinary JMeter variable: per-thread, and gone at the end of the thread's life. Each simulated user gets its own `orderId`, which is exactly what you want when every user is placing a different order. ## Putting it together Sampler posts the order, JSON Extractor underneath it names `orderId` with Match No. `1` and default `NO_ORDER_ID`, next sampler asks for `/orders/${orderId}`. Three fields and one placement decision, and the value carries forward.

  • The extractor found no match. What is in the variable, and did the sampler fail?
    The variable holds the Default Value and `orderId_matchNr` is set to `0`. The sampler is untouched — the JSON Extractor does not add an assertion result and does not mark the sample unsuccessful, so a run can stay green while every capture is silently falling back to its default.
  • You left Match No. empty and the plan works most of the time but not always. Why?
    An empty Match No. is read as `0`, which means random selection among the matches. With one match it behaves like `1`; the moment the body carries two, each thread gets whichever one the random draw picked, so the plan works intermittently rather than failing outright.
  • Can the JSON Extractor read a value out of a response header?
    No. It has no field-to-check selector. It reads the response body of the samples its Apply to setting selects, or the contents of a named JMeter variable when Apply to is set to a variable. Header values need a different extractor.

saying these in an interview costs you the question

  • Claims JMeter needs a script to read a JSON body
  • Puts the extractor beside the sampler rather than under it
  • Leaves Default Values blank, so a miss goes unnoticed
  • Thinks a failed extraction marks the sample as failed
  • Reads a blank Match No. as meaning the first match