Response Templating - Working with JSON

Extracting data with JSONPath

WireMock Cloud provides the jsonPath helper which will extract values from a JSON document using the JSONPath expression language.

Similar in concept to XPath, JSONPath permits selection of individual values or sub-documents via a query expression.

For example, given the JSON

{
  "outer": {
    "inner": "Stuff"
  }
}

The following will render “Stuff” into the output:

{{jsonPath request.body '$.outer.inner'}}

And for the same JSON the following will render { "inner": "Stuff" }:

{{jsonPath request.body '$.outer'}}

Iterating over JSON elements

The jsonPath helper outputs a “one or many” collection, which can either be printed directly, or passed to further helpers such as each or join.

For instance, given a request body of the form:

{
  "things": [
    {
      "id": 1
    },
    {
      "id": 2
    },
    {
      "id": 3
    }
  ]
}

And the following response body template:

{{#each (jsonPath request.body '$.things') as |thing|}}
thing: {{{thing.id}}}{{/each}}

The response body will contain:

thing: 1
thing: 2
thing: 3

The above will only work if the JSONPath expression selects an array from the request JSON. However, each can also be used to iterate over maps/objects, so given the request JSON:

{
  "things": {
    "one": 1,
    "two": 2,
    "three": 3
  }
}

And the template:

{{#each (jsonPath request.body '$.things') as |value key|}}
{{{key}}}={{{value}}}{{/each}}

The output would contain:

one=1
two=2
three=3

Adding to a JSON Array

The jsonArrayAdd helper allows you to append an element to an existing json array.

Its simplest form just takes two parameters, the array to append to and the item to be added:

{{jsonArrayAdd existingArray newItem}}

You can also use it in block form to parse the contents of the block as the new item to add:

{{#jsonArrayAdd existingArray}}
{
  "id": 321,
  "name": "sam"
}
{{/jsonArrayAdd}}

It may be convenient to default the array to an empty array if it does not exist:

{{#jsonArrayAdd (val existingArray or='[]')}}
{
  "id": 321,
  "name": "sam"
}
{{/jsonArrayAdd}}

Removing from a JSON Array or Object

The jsonRemove helper allows you to remove an element from an existing json array, or remove a key from an existing json object, by identifying it using a json path expression.

For instance, given an existing array like this:

{{#assign 'existingArray'}}
[
  { "id": 456, "name": "bob"},
  { "id": 123, "name": "alice"},
  { "id": 321, "name": "sam"}
]
{{/assign}}

application of this helper, which selects the object with id 123:

{{jsonRemove existingArray '$.[?(@.id == 123)]'}}

will return this array:

[
  { "id": 456, "name": "bob"},
  { "id": 321, "name": "sam"}
]

Given an object like this:

{{#assign 'existingObject'}}
{ "id": 456, "name": "bob"}
{{/assign}}

application of this helper, which selects the key name:

{{jsonRemove existingObject '$.name'}}

will return this object:

{ "id": 456 }

Merging JSON objects

The jsonMerge helper allows you to merge two json objects. Merging will recurse into any common keys where the values are both objects, but not into any array values, where the value in the second object will overwrite that in the first.

Given these two objects:

{{#assign 'object1'}}
{
  "id": 456, 
  "forename": "Robert",
  "surname": "Smith",
  "address": {
    "number": "12"
  },
  "hobbies": [ "chess", "football" ]
}
{{/assign}}
{{#assign 'object2'}}
{
  "name": "Robert",
  "nickname": "Bob",
  "address": {
    "street": "High Street"
  },
  "hobbies": [ "rugby" ]
}
{{/assign}}
{{jsonMerge object1 object2}}

will return this object:

{
  "id": 456,
  "forename": "Robert",
  "surname": "Smith",
  "nickname": "Bob",
  "address": {
    "number": "12",
    "street": "High Street"
  },
  "hobbies": [ "rugby" ]
}

Like the jsonArrayAdd helper, the second object can be provided as a block:

{{#jsonMerge object1}}
{
  "name": "Robert",
  "nickname": "Bob",
  "address": {
    "street": "High Street"
  },
  "hobbies": [ "rugby" ]
}
{{/jsonMerge}}

Formatting JSON

The formatJson helper allows you to output JSON in either a pretty or a compact format. The default is pretty:

{{#assign 'object1'}}
{"id": 456,
     "forename": "Robert", "surname": "Smith",
  "address": {
    "number": "12"
},
"hobbies": [ "chess", 
"football" ]
}
{{/assign}}
{{formatJson object1}}

emits:

{
  "id" : 456,
  "forename" : "Robert",
  "surname" : "Smith",
  "address" : {
    "number" : "12"
  },
  "hobbies" : [ "chess", "football" ]
}

Whereas

{{formatJson object1 format='compact'}}

emits

{"id":456,"forename":"Robert","surname":"Smith","address":{"number":"12"},"hobbies":["chess","football"]}

The json to format can also be supplied as a block body:

{{#formatJson}}
{"id": 456,
     "forename": "Robert", "surname": "Smith",
  "address": {
    "number": "12"
},
"hobbies": [ "chess", 
"football" ]
}
{{/formatJson}}

Reading object as JSON

The parseJson helper will take the string value of the provided variable (or the contents of the block) and parse it into an object or array, and assign it to the given variable.

e.g.

{{#parseJson 'newVariableName'}}
    [ "shoes", "socks" ]
{{/parseJson}}

will add an array called newVariableName that can be used in subsequent helpers.

The contents to parse can also be supplied inline:

{{#assign 'inputString'}}
    [ "shoes", "socks" ]
{{/assign}}
{{parseJson inputString 'newVariableName'}}

If no variable name is supplied the result of the parsing is output.

Writing data as a JSON string

The toJson helper will convert any object into a JSON string.

{{toJson (array 1 2 3)}}

emits

[ 1, 2, 3 ]