Docs JsonPath Guide

JsonPath Guide for Mockarty

Table of Contents

  1. What is JsonPath
  2. Basic Syntax
  3. Usage Examples
  4. Data Extraction
  5. Variables in Responses
  6. Store Access
  7. Faker Integration
  8. Advanced Examples

Tip: Code examples are available for cURL, CLI, and SDK clients (Go, Python, Java). See the SDK Guide for installation and setup. See the CLI User Guide for the command-line tool.

About URLs in examples: All examples use localhost:5770 as the default Mockarty address. If your instance runs on a remote server, replace localhost:5770 with its actual address (e.g. https://mockarty.company.com or http://192.168.1.50:5770). See Tips & Useful Features for details.

What is JsonPath

JsonPath is a query language for JSON documents, similar to XPath for XML. Think of it as an “address” system for data inside JSON – just like a street address helps you find a house in a city, a JsonPath expression helps you find a specific value inside a JSON document.

For example, if you have a JSON object {"user": {"name": "John"}}, the expression $.user.name points directly to "John". The $ symbol means “start at the root of the document”, and dots navigate deeper into nested objects.

When would you use it? Whenever you need your mock to be dynamic rather than static. For instance, if a client sends a request with a user ID, you can use JsonPath to extract that ID and include it in the response – making the mock behave like a real service.

In Mockarty, JsonPath is used for:

  • Extracting data from incoming requests
  • Accessing Store data (Global, Chain, Mock)
  • Generating dynamic responses with variables using Faker
  • Evaluating conditions for mock matching

Library

Mockarty uses the github.com/PaesslerAG/jsonpath library with extended syntax support.


Basic Syntax

Basic Expressions

Expression Description Example
$ Document root $.user
. Current node $.user.name
[] Index/key access $.items[0], $.user['name']
* All elements $.users[*].name
.. Recursive search $..email
?() Filter $.items[?(@.price > 100)]

Tip: The dot after $ is optional – $req.field is automatically normalized to $.req.field.

Mockarty Special Prefixes

Prefix Description Example
$.req Request body $.req.userId
$.reqHeader Request headers $.reqHeader.Authorization[0]
$.queryParams HTTP query parameters $.queryParams.limit
$.mS Mock Store $.mS.savedValue
$.cS Chain Store $.cS.sessionId
$.gS Global Store $.gS.counter
$.pathParam URL path parameters $.pathParam.id for route /api/users/:id
$.fake Faker data $.fake.FirstName
$.response Response data (for webhook) $.response.orderId
$.namespace Current namespace $.namespace

Math Functions

Function Description Example
$.increment(expr || default) Increment value by 1 $.increment($.gS.counter || 0)
$.sum(expr1, expr2) Sum of two values $.sum($.req.price, $.req.tax)
$.multiply(expr1, expr2) Multiply two values $.multiply($.req.quantity, $.req.price)
$.subtract(expr1, expr2) Subtraction (expr1 - expr2) $.subtract($.req.total, $.req.discount)

Arguments can be:

  • Numeric literals: $.sum(10, 20)
  • JsonPath expressions: $.sum($.req.a, $.req.b)
  • Store references: $.sum($.gS.total, $.req.amount)
  • Expressions with default: $.increment($.gS.counter || 0) – if the value is missing, 0 is used

Usage Examples

Simple Extraction

JSON document:

{
  "user": {
    "id": 123,
    "name": "John Doe",
    "email": "john@example.com"
  }
}

JsonPath expressions:

$.user.id        // → 123
$.user.name      // → "John Doe"
$.user.email     // → "john@example.com"
$['user']['id']  // → 123 (alternative syntax)

Working with Arrays

JSON document:

{
  "users": [
    {"id": 1, "name": "John", "active": true},
    {"id": 2, "name": "Jane", "active": false},
    {"id": 3, "name": "Bob", "active": true}
  ]
}

JsonPath expressions:

$.users[0]             // → {"id": 1, "name": "John", "active": true}
$.users[0].name        // → "John"
$.users[-1]            // → {"id": 3, "name": "Bob", "active": true} (last element)
$.users[*].name        // → ["John", "Jane", "Bob"]
$.users[*].id          // → [1, 2, 3]

Filtering

// Active users
$.users[?(@.active == true)]
// → [{"id": 1, "name": "John", "active": true}, {"id": 3, "name": "Bob", "active": true}]

// Names of active users
$.users[?(@.active == true)].name
// → ["John", "Bob"]

// Users with ID greater than 1
$.users[?(@.id > 1)]

// Users with name containing "J"
$.users[?(@.name =~ /.*J.*/i)]

JSON document:

{
  "company": {
    "departments": [
      {
        "name": "IT",
        "employees": [
          {"name": "John", "email": "john@company.com"},
          {"name": "Jane", "email": "jane@company.com"}
        ]
      },
      {
        "name": "HR",
        "head": {"name": "Bob", "email": "bob@company.com"}
      }
    ]
  }
}

JsonPath expressions:

$..email    // → ["john@company.com", "jane@company.com", "bob@company.com"]
$..name     // → ["IT", "John", "Jane", "HR", "Bob"]

Data Extraction

Extracting from Request

HTTP request:

POST /api/users
{
  "user": {
    "name": "John Doe",
    "email": "john@example.com",
    "preferences": {
      "theme": "dark",
      "notifications": true
    }
  }
}

Extraction in Mock:

{
  "extract": {
    "mStore": {
      "userName": "$.req.user.name",
      "userEmail": "$.req.user.email",
      "userTheme": "$.req.user.preferences.theme"
    },
    "gStore": {
      "lastUserName": "$.req.user.name"
    }
  }
}

Extracting Headers

HTTP request:

POST /api/data
Authorization: Bearer abc123token
Content-Type: application/json
X-User-ID: user-456

Extraction:

{
  "extract": {
    "mStore": {
      "authToken": "$.reqHeader.Authorization[0]",
      "userId": "$.reqHeader['X-User-ID'][0]",
      "contentType": "$.reqHeader['Content-Type'][0]"
    }
  }
}

Important: Headers are arrays (a single header can have multiple values). Use [0] to get the first value.

Extracting Query Parameters

For query strings (?limit=10&offset=20) use $.queryParams:

Request: GET /api/users?limit=10&offset=20&sort=name

{
  "response": {
    "payload": {
      "limit": "$.queryParams.limit",
      "offset": "$.queryParams.offset",
      "sort": "$.queryParams.sort"
    }
  }
}

You can use query parameters in conditions:

{
  "conditions": [
    {
      "queryParam": "status",
      "assertAction": "equals",
      "value": "active"
    }
  ]
}

Complex Conditions

{
  "conditions": [
    {
      "path": "$.order.items[*].price",
      "assertAction": "contains",
      "value": 100
    },
    {
      "path": "$.order.items[?(@.category == 'electronics')].price",
      "assertAction": "matches",
      "value": "^[1-9]\\d{2,}$"
    }
  ]
}

Variables in Responses

Using Extracted Data

{
  "response": {
    "statusCode": 201,
    "payload": {
      "id": "$.fake.UUIDDigit",
      "name": "$.req.user.name",
      "email": "$.req.user.email",
      "welcomeMessage": "Hello $.req.user.name!",
      "timestamp": "$.fake.RFC3339",
      "preferences": "$.req.user.preferences"
    }
  }
}

Combining Values

{
  "response": {
    "payload": {
      "fullName": "$.req.firstName $.req.lastName",
      "displayName": "Mr. $.req.lastName",
      "loginUrl": "https://example.com/login?user=$.req.userId"
    }
  }
}

Store Access

For a complete guide on Store systems, see the Store Systems documentation.

Global Store

Saving to Global Store:

{
  "extract": {
    "gStore": {
      "totalUsers": "$.increment($.gS.totalUsers || 0)",
      "lastActiveUser": "$.req.userId",
      "systemStats": {
        "lastRequest": "$.fake.RFC3339",
        "version": "1.0.0"
      }
    }
  }
}

Using Global Store:

{
  "response": {
    "payload": {
      "userId": "$.req.id",
      "totalUsersInSystem": "$.gS.totalUsers",
      "lastActiveUser": "$.gS.lastActiveUser",
      "systemVersion": "$.gS.systemStats.version"
    }
  }
}

Chain Store

First mock in the chain:

{
  "chainId": "user-registration",
  "extract": {
    "cStore": {
      "userId": "$.fake.UUIDDigit",
      "userEmail": "$.req.email",
      "registrationTime": "$.fake.RFC3339"
    }
  },
  "response": {
    "payload": {
      "userId": "$.cS.userId",
      "status": "registered"
    }
  }
}

Second mock in the chain:

{
  "chainId": "user-registration",
  "response": {
    "payload": {
      "userId": "$.cS.userId",
      "email": "$.cS.userEmail",
      "registeredAt": "$.cS.registrationTime",
      "status": "verified"
    }
  }
}

Faker Integration

For a complete list of all available Faker functions, see the Faker Reference.

Basic Faker Functions

{
  "response": {
    "payload": {
      "id": "$.fake.UUID",
      "name": "$.fake.FirstName",
      "lastName": "$.fake.LastName",
      "email": "$.fake.Email",
      "phone": "$.fake.Phone",
      "address": "$.fake.Address",
      "city": "$.fake.City",
      "country": "$.fake.Country",
      "company": "$.fake.Company",
      "jobTitle": "$.fake.JobTitle",
      "website": "$.fake.URL",
      "avatar": "$.fake.URL",
      "birthDate": "$.fake.Date",
      "timestamp": "$.fake.RFC3339",
      "unixTime": "$.fake.UnixTime"
    }
  }
}

Numeric Faker Functions

{
  "response": {
    "payload": {
      "randomInt": "$.fake.Int",
      "positiveInt": "$.fake.PositiveInt",
      "negativeInt": "$.fake.NegativeInt",
      "float": "$.fake.Float",
      "price": "$.fake.Price",
      "latitude": "$.fake.Latitude",
      "longitude": "$.fake.Longitude",
      "boolean": "$.fake.Bool"
    }
  }
}

Localized Data

{
  "response": {
    "payload": {
      "russianName": "$.fake.RussianFirstNameMale",
      "russianSurname": "$.fake.RussianLastNameMale",
      "chineseName": "$.fake.FirstName",
      "germanName": "$.fake.FirstName",
      "sentence": "$.fake.Sentence",
      "paragraph": "$.fake.Paragraph",
      "word": "$.fake.Word"
    }
  }
}

Math Operations

Detailed Examples

Counter with Increment

{
  "extract": {
    "gStore": {
      "visitCount": "$.increment($.gS.visitCount || 0)"
    }
  },
  "response": {
    "payload": {
      "visits": "$.gS.visitCount"
    }
  }
}

On each call, visitCount is incremented by 1. The || 0 construct sets the initial value if the key does not exist.

Summation and Multiplication

{
  "response": {
    "payload": {
      "subtotal": "$.req.price",
      "tax": "$.multiply($.req.price, 0.2)",
      "total": "$.sum($.req.price, $.multiply($.req.price, 0.2))",
      "discount": "$.subtract($.req.price, 10)"
    }
  }
}

Important: Math functions work with numeric values. Strings are automatically converted to numbers. If conversion is not possible, the value 0 is used.

String Interpolation

JsonPath expressions can be embedded directly into text strings:

{
  "response": {
    "payload": {
      "greeting": "Hello $.req.name, welcome!",
      "link": "https://example.com/users/$.req.id/profile",
      "message": "Order #$.fake.UUIDDigit confirmed for $.req.email"
    }
  }
}

All $.xxx expressions within strings are automatically replaced with their corresponding values.


Advanced Examples

Dynamic Counter

{
  "id": "counter-example",
  "http": {
    "route": "/api/counter"
  },
  "response": {
    "payload": {
      "currentCount": "$.gS.counter",
      "incrementedCount": "$.increment($.gS.counter || 0)",
      "timestamp": "$.fake.RFC3339"
    }
  },
  "extract": {
    "gStore": {
      "counter": "$.increment($.gS.counter || 0)",
      "lastIncrement": "$.fake.RFC3339"
    }
  }
}

User Management Chain

Registration (Step 1):

{
  "id": "user-register",
  "chainId": "user-lifecycle",
  "http": {
    "route": "/api/v1/auth/register",
    "httpMethod": "POST"
  },
  "response": {
    "payload": {
      "userId": "$.fake.UUIDDigit",
      "email": "$.req.email",
      "status": "pending_verification",
      "verificationCode": "$.fake.ZipCode"
    }
  },
  "extract": {
    "cStore": {
      "userId": "$.fake.UUIDDigit",
      "userEmail": "$.req.email",
      "verificationCode": "$.fake.ZipCode",
      "registeredAt": "$.fake.RFC3339"
    },
    "gStore": {
      "totalRegistrations": "$.increment($.gS.totalRegistrations || 0)"
    }
  }
}

Verification (Step 2):

{
  "id": "user-verify",
  "chainId": "user-lifecycle",
  "http": {
    "route": "/api/v1/auth/verify",
    "httpMethod": "POST",
    "conditions": [
      {
        "assertAction": "equals",
        "value": {
          "code": "$.cS.verificationCode"
        }
      }
    ]
  },
  "response": {
    "payload": {
      "userId": "$.cS.userId",
      "email": "$.cS.userEmail",
      "status": "verified",
      "verifiedAt": "$.fake.RFC3339",
      "accessToken": "$.fake.JWT"
    }
  },
  "extract": {
    "cStore": {
      "isVerified": true,
      "verifiedAt": "$.fake.RFC3339",
      "accessToken": "$.fake.JWT"
    }
  }
}

Profile (Step 3):

{
  "id": "user-profile",
  "chainId": "user-lifecycle",
  "http": {
    "route": "/api/users/profile",
    "httpMethod": "GET",
    "header": [
      {
        "assertAction": "contains",
        "value": {
          "Authorization": "Bearer $.cS.accessToken"
        }
      }
    ]
  },
  "response": {
    "payload": {
      "userId": "$.cS.userId",
      "email": "$.cS.userEmail",
      "verified": "$.cS.isVerified",
      "registeredAt": "$.cS.registeredAt",
      "verifiedAt": "$.cS.verifiedAt",
      "profile": {
        "name": "$.fake.FirstName",
        "lastName": "$.fake.LastName",
        "avatar": "$.fake.URL",
        "bio": "$.fake.Sentence",
        "preferences": {
          "theme": "dark",
          "language": "en",
          "notifications": true
        }
      },
      "stats": {
        "loginCount": "$.fake.Number",
        "lastLogin": "$.fake.RFC3339",
        "totalUsers": "$.gS.totalRegistrations"
      }
    }
  }
}

E-commerce Order Processing

{
  "id": "process-order",
  "http": {
    "route": "/api/orders",
    "httpMethod": "POST",
    "conditions": [
      {
        "path": "$.items[*].quantity",
        "assertAction": "matches",
        "value": "^[1-9]\\d*$"
      },
      {
        "path": "$.customer.email",
        "assertAction": "matches",
        "value": "^[\\w\\.-]+@[\\w\\.-]+\\.[a-zA-Z]{2,}$"
      }
    ]
  },
  "response": {
    "payload": {
      "orderId": "$.fake.UUIDDigit",
      "customer": "$.req.customer",
      "items": "$.req.items",
      "summary": {
        "estimatedTotal": "$.fake.Float",
        "currency": "USD",
        "orderedItems": "$.req.items"
      },
      "fulfillment": {
        "estimatedDelivery": "$.fake.Date",
        "trackingNumber": "$.fake.ZipCode",
        "carrier": "$.fake.Company"
      },
      "timestamps": {
        "orderedAt": "$.fake.RFC3339",
        "estimatedShipping": "$.fake.Date",
        "estimatedDelivery": "$.fake.Date"
      }
    }
  },
  "extract": {
    "mStore": {
      "orderId": "$.fake.UUIDDigit",
      "customerEmail": "$.req.customer.email"
    },
    "gStore": {
      "totalOrders": "$.increment($.gS.totalOrders || 0)",
      "lastOrderTime": "$.fake.RFC3339"
    }
  }
}

Analytics Mock

{
  "id": "analytics-report",
  "http": {
    "route": "/api/analytics/report",
    "queryParams": [
      {
        "path": "$.period",
        "assertAction": "matches",
        "value": "^(daily|weekly|monthly)$"
      }
    ]
  },
  "response": {
    "payload": {
      "report": {
        "period": "$.queryParams.period",
        "generatedAt": "$.fake.RFC3339",
        "metrics": {
          "totalUsers": "$.gS.totalRegistrations",
          "totalOrders": "$.gS.totalOrders",
          "activeUsers": "$.fake.Number",
          "revenue": "$.fake.Float",
          "conversionRate": "$.fake.Float"
        },
        "trends": {
          "userGrowth": "$.fake.Float",
          "orderGrowth": "$.fake.Float",
          "revenueGrowth": "$.fake.Float"
        },
        "topProducts": [
          {
            "id": "$.fake.UUIDDigit",
            "name": "$.fake.Word",
            "sales": "$.fake.Number",
            "revenue": "$.fake.Float"
          }
        ]
      }
    }
  }
}

Utilities for Working with JsonPath

Utils page – JsonPath tester

Testing JsonPath

Mockarty exposes a utility endpoint for testing JsonPath expressions against arbitrary JSON without creating a mock. This is exposed via the Utils page in the admin UI and via a REST endpoint.

Endpoint: POST /api/v1/utils/extract-jpath

Request body:

Field Type Description
jpath string JsonPath expression to evaluate
from object JSON document to evaluate the expression against

cURL example:

curl -X POST http://localhost:5770/api/v1/utils/extract-jpath \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $MOCKARTY_API_TOKEN" \
  -d '{
    "jpath": "$.users[*].email",
    "from": {
      "users": [
        {"name": "John", "email": "john@example.com"},
        {"name": "Jane", "email": "jane@example.com"}
      ]
    }
  }'

Response:

{
  "extract": ["john@example.com", "jane@example.com"]
}

The endpoint is intentionally SDK-agnostic — it’s a debugging helper, not part of the automation surface. SDKs (Go/Python/Java) and the CLI do not expose a dedicated wrapper; use a plain HTTP POST from your language of choice, or the Utils → JsonPath Tester page in the admin UI.

Debugging Expressions

Example debug mock:

{
  "id": "debug-jsonpath",
  "http": {
    "route": "/debug/jsonpath"
  },
  "response": {
    "payload": {
      "request": "$.req",
      "headers": "$.reqHeader",
      "mockStore": "$.mS",
      "chainStore": "$.cS",
      "globalStore": "$.gS",
      "fakeData": {
        "uuid": "$.fake.UUID",
        "name": "$.fake.FirstName",
        "email": "$.fake.Email"
      }
    }
  }
}

Known Limitations

When using JsonPath expressions embedded in JSON string values (not as the entire field value), these limitations apply due to the regex-based interpolation engine:

Feature Standalone value Embedded in string
Simple paths $.req.user.id Works Works
Array index $.req.items[0] Works Works
Negative index $.req.items[-1] Works Does NOT work
Wildcard $.req.items[*].name Works Does NOT work
Recursive descent $..email Works Does NOT work
Filter $.items[?(@.price>100)] Works Does NOT work

Fallback || syntax only works inside math function arguments:

  • Works: $.increment($.gS.counter || 0)
  • Does NOT work as standalone: $.req.userId || "default"

Unresolved expressions produce an error string like "Error: JSONPath '$.req.missing' not found" in both JSON and XML responses. This applies to standalone $.xxx values and to $.xxx expressions embedded in strings. Use the || default syntax inside math functions (e.g., $.increment($.gS.counter || 0)) to handle missing values gracefully.

Recursion depth is limited to 15 levels of nested JSON objects.


Best Practices

  1. Use meaningful names in Store:

    "extract": {
      "cStore": {
        "userId": "$.req.id",
        "userEmail": "$.req.email",
        "sessionStartTime": "$.fake.RFC3339"
      }
    }
    
  2. Use || fallback in math functions to handle missing values:

    $.increment($.gS.counter || 0)
    $.sum($.gS.price || 0, $.req.tax)
    

    Note: The || fallback syntax only works inside math function arguments ($.increment, $.sum, $.multiply, $.subtract). It does NOT work as a standalone expression like $.req.user.id || "default-id".

  3. Use filters for complex logic:

    $.orders[?(@.status == 'completed' && @.amount > 100)]
    
  4. Combine static and dynamic data:

    {
      "message": "Hello $.req.name! Your order #$.fake.UUIDDigit is confirmed",
      "timestamp": "$.fake.RFC3339"
    }
    

XML Support

JsonPath expressions also work inside XML responses (SOAP mocks):

{
  "response": {
    "payload": "<GetUserResponse><UserId>$.req.id</UserId><Name>$.fake.FirstName</Name><Email>$.fake.Email</Email></GetUserResponse>"
  }
}

Mockarty automatically escapes XML special characters (<, >, &, ", ') when substituting values into XML strings. It also normalizes whitespace in namespaces and attributes.


Go Template Mode

In addition to JsonPath, Mockarty supports Go Template syntax for file templates. Load a template from a file using the templateFile field:

{
  "response": {
    "templateFile": "my-template.json"
  }
}

Available functions inside Go Template:

Function Description Example
req Request data (zero-arg, returns request object) {{(req).user.name}}
reqHeader Header data (zero-arg, returns headers map) {{index (reqHeader) "Authorization"}}
fake Faker data (zero-arg, returns faker object) {{(fake).FirstName}}
mS Mock Store (zero-arg, returns store map) {{index (mS) "key"}}
cS Chain Store (zero-arg, returns store map) {{index (cS) "key"}}
gS Global Store (zero-arg, returns store map) {{index (gS) "key"}}
asJson Convert to JSON {{asJson .Request}}

Important: Go Template and JsonPath are two different modes. JsonPath works in payload fields (JSON), Go Template works in templateFile.


Use this guide to create powerful dynamic mocks with JsonPath!


See Also

  • Faker Reference – all available Faker functions for generating test data
  • Store Systems – Global, Chain, and Mock stores for stateful mocks
  • API Reference – complete REST API including the JsonPath test endpoint
  • Web UI Guide – visual mock constructor with JsonPath support
  • Quick Start – get started with your first dynamic mock