JsonPath руководство для Mockarty
Содержание
- Что такое JsonPath
- Основной синтаксис
- Примеры использования
- Извлечение данных
- Переменные в ответах
- Store доступ
- Faker интеграция
- Сложные примеры
Совет: Примеры кода доступны для cURL, CLI и SDK-клиентов (Go, Python, Java). Смотрите Руководство по SDK для установки и настройки. Смотрите Руководство по CLI для командной утилиты.
URL-адреса в примерах: Во всех примерах используется
localhost:5770как адрес Mockarty по умолчанию. Если ваш экземпляр работает на удалённом сервере, заменитеlocalhost:5770на реальный адрес (например,https://mockarty.company.comилиhttp://192.168.1.50:5770). Подробнее — в разделе Полезные функции и советы.
Что такое JsonPath
JsonPath – это язык запросов для JSON-документов, аналогичный XPath для XML. Представьте его как систему “адресов” для данных внутри JSON – точно так же, как почтовый адрес помогает найти дом в городе, JsonPath-выражение помогает найти конкретное значение внутри JSON-документа.
Например, если у вас есть JSON-объект {"user": {"name": "John"}}, выражение $.user.name указывает прямо на "John". Символ $ означает “начать с корня документа”, а точки позволяют перемещаться вглубь вложенных объектов.
Когда это нужно? Всякий раз, когда вы хотите, чтобы мок вёл себя динамически, а не возвращал статичный ответ. Например, если клиент отправляет запрос с ID пользователя, вы можете с помощью JsonPath извлечь этот ID и включить его в ответ – и мок будет вести себя как настоящий сервис.
В Mockarty JsonPath используется для:
- Извлечения данных из входящих запросов
- Доступа к Store данным (Global, Chain, Mock)
- Генерации динамических ответов с переменными через Faker
- Проверки условий при мэтчинге моков
Библиотека
Mockarty использует библиотеку github.com/PaesslerAG/jsonpath с поддержкой расширенного синтаксиса.
Основной синтаксис
Базовые выражения
| Выражение | Описание | Пример |
|---|---|---|
$ |
Корень документа | $.user |
. |
Текущий узел | $.user.name |
[] |
Доступ по индексу/ключу | $.items[0], $.user['name'] |
* |
Все элементы | $.users[*].name |
.. |
Рекурсивный поиск | $..email |
?() |
Фильтр | $.items[?(@.price > 100)] |
Совет: Точка после
$необязательна –$req.fieldавтоматически нормализуется в$.req.field.
Специальные префиксы Mockarty
| Префикс | Описание | Пример |
|---|---|---|
$.req |
Тело запроса | $.req.userId |
$.reqHeader |
Заголовки запроса | $.reqHeader.Authorization[0] |
$.queryParams |
Query параметры HTTP | $.queryParams.limit |
$.mS |
Mock Store | $.mS.savedValue |
$.cS |
Chain Store | $.cS.sessionId |
$.gS |
Global Store | $.gS.counter |
$.pathParam |
Параметры URL-пути | $.pathParam.id для маршрута /api/users/:id |
$.fake |
Faker данные | $.fake.FirstName |
$.response |
Данные ответа (для webhook) | $.response.orderId |
$.namespace |
Текущий namespace | $.namespace |
Математические функции
| Функция | Описание | Пример |
|---|---|---|
$.increment(expr || default) |
Увеличить значение на 1 | $.increment($.gS.counter || 0) |
$.sum(expr1, expr2) |
Сумма двух значений | $.sum($.req.price, $.req.tax) |
$.multiply(expr1, expr2) |
Умножение двух значений | $.multiply($.req.quantity, $.req.price) |
$.subtract(expr1, expr2) |
Вычитание (expr1 - expr2) | $.subtract($.req.total, $.req.discount) |
Аргументами могут быть:
- Числовые литералы:
$.sum(10, 20) - JsonPath выражения:
$.sum($.req.a, $.req.b) - Store ссылки:
$.sum($.gS.total, $.req.amount) - Выражения с default:
$.increment($.gS.counter || 0)– если значение отсутствует, используется0
Примеры использования
Простое извлечение
JSON документ:
{
"user": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
}
}
JsonPath выражения:
$.user.id // → 123
$.user.name // → "John Doe"
$.user.email // → "john@example.com"
$['user']['id'] // → 123 (альтернативный синтаксис)
Работа с массивами
JSON документ:
{
"users": [
{"id": 1, "name": "John", "active": true},
{"id": 2, "name": "Jane", "active": false},
{"id": 3, "name": "Bob", "active": true}
]
}
JsonPath выражения:
$.users[0] // → {"id": 1, "name": "John", "active": true}
$.users[0].name // → "John"
$.users[-1] // → {"id": 3, "name": "Bob", "active": true} (последний)
$.users[*].name // → ["John", "Jane", "Bob"]
$.users[*].id // → [1, 2, 3]
Фильтрация
// Активные пользователи
$.users[?(@.active == true)]
// → [{"id": 1, "name": "John", "active": true}, {"id": 3, "name": "Bob", "active": true}]
// Имена активных пользователей
$.users[?(@.active == true)].name
// → ["John", "Bob"]
// Пользователи с ID больше 1
$.users[?(@.id > 1)]
// Пользователи с именем содержащим "J"
$.users[?(@.name =~ /.*J.*/i)]
Рекурсивный поиск
JSON документ:
{
"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 выражения:
$..email // → ["john@company.com", "jane@company.com", "bob@company.com"]
$..name // → ["IT", "John", "Jane", "HR", "Bob"]
Извлечение данных
Извлечение из запроса
HTTP запрос:
POST /api/users
{
"user": {
"name": "John Doe",
"email": "john@example.com",
"preferences": {
"theme": "dark",
"notifications": true
}
}
}
Извлечение в Mock:
{
"extract": {
"mStore": {
"userName": "$.req.user.name",
"userEmail": "$.req.user.email",
"userTheme": "$.req.user.preferences.theme"
},
"gStore": {
"lastUserName": "$.req.user.name"
}
}
}
Извлечение заголовков
HTTP запрос:
POST /api/data
Authorization: Bearer abc123token
Content-Type: application/json
X-User-ID: user-456
Извлечение:
{
"extract": {
"mStore": {
"authToken": "$.reqHeader.Authorization[0]",
"userId": "$.reqHeader['X-User-ID'][0]",
"contentType": "$.reqHeader['Content-Type'][0]"
}
}
}
Важно: Заголовки – это массивы (один заголовок может иметь несколько значений). Используйте
[0]для получения первого значения.
Извлечение query параметров
Для query строки (?limit=10&offset=20) используйте $.queryParams:
Запрос: GET /api/users?limit=10&offset=20&sort=name
{
"response": {
"payload": {
"limit": "$.queryParams.limit",
"offset": "$.queryParams.offset",
"sort": "$.queryParams.sort"
}
}
}
Можно использовать query параметры в условиях:
{
"conditions": [
{
"queryParam": "status",
"assertAction": "equals",
"value": "active"
}
]
}
Сложные условия
{
"conditions": [
{
"path": "$.order.items[*].price",
"assertAction": "contains",
"value": 100
},
{
"path": "$.order.items[?(@.category == 'electronics')].price",
"assertAction": "matches",
"value": "^[1-9]\\d{2,}$"
}
]
}
Переменные в ответах
Использование извлеченных данных
{
"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"
}
}
}
Объединение значений
{
"response": {
"payload": {
"fullName": "$.req.firstName $.req.lastName",
"displayName": "Mr. $.req.lastName",
"loginUrl": "https://example.com/login?user=$.req.userId"
}
}
}
Store доступ
Полное руководство по системам хранилищ см. в документации Store Systems.
Global Store
Сохранение в Global Store:
{
"extract": {
"gStore": {
"totalUsers": "$.increment($.gS.totalUsers || 0)",
"lastActiveUser": "$.req.userId",
"systemStats": {
"lastRequest": "$.fake.RFC3339",
"version": "1.0.0"
}
}
}
}
Использование Global Store:
{
"response": {
"payload": {
"userId": "$.req.id",
"totalUsersInSystem": "$.gS.totalUsers",
"lastActiveUser": "$.gS.lastActiveUser",
"systemVersion": "$.gS.systemStats.version"
}
}
}
Chain Store
Первый мок в цепочке:
{
"chainId": "user-registration",
"extract": {
"cStore": {
"userId": "$.fake.UUIDDigit",
"userEmail": "$.req.email",
"registrationTime": "$.fake.RFC3339"
}
},
"response": {
"payload": {
"userId": "$.cS.userId",
"status": "registered"
}
}
}
Второй мок в цепочке:
{
"chainId": "user-registration",
"response": {
"payload": {
"userId": "$.cS.userId",
"email": "$.cS.userEmail",
"registeredAt": "$.cS.registrationTime",
"status": "verified"
}
}
}
Faker интеграция
Полный список всех доступных Faker-функций см. в Справочнике Faker.
Основные Faker функции
{
"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"
}
}
}
Числовые Faker функции
{
"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"
}
}
}
Локализованные данные
{
"response": {
"payload": {
"russianName": "$.fake.RussianFirstNameMale",
"russianSurname": "$.fake.RussianLastNameMale",
"chineseName": "$.fake.FirstName",
"germanName": "$.fake.FirstName",
"sentence": "$.fake.Sentence",
"paragraph": "$.fake.Paragraph",
"word": "$.fake.Word"
}
}
}
Математические операции
Подробные примеры
Счетчик с инкрементом
{
"extract": {
"gStore": {
"visitCount": "$.increment($.gS.visitCount || 0)"
}
},
"response": {
"payload": {
"visits": "$.gS.visitCount"
}
}
}
При каждом вызове visitCount увеличивается на 1. Конструкция || 0 задает начальное значение, если ключ отсутствует.
Суммирование и умножение
{
"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)"
}
}
}
Важно: Математические функции работают с числовыми значениями. Строки автоматически преобразуются в числа. Если преобразование невозможно, используется значение 0.
Строковая интерполяция
JsonPath выражения можно встраивать прямо в текстовые строки:
{
"response": {
"payload": {
"greeting": "Hello $.req.name, welcome!",
"link": "https://example.com/users/$.req.id/profile",
"message": "Order #$.fake.UUIDDigit confirmed for $.req.email"
}
}
}
Все выражения $.xxx внутри строк будут автоматически заменены на соответствующие значения.
Сложные примеры
Динамический счетчик
{
"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
Регистрация (Шаг 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)"
}
}
}
Верификация (Шаг 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"
}
}
}
Профиль (Шаг 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"
}
]
}
}
}
}
Утилиты для работы с JsonPath

Тестирование JsonPath
Mockarty предоставляет утилитарный endpoint для тестирования JsonPath-выражений на произвольном JSON без создания мока. Доступен через страницу Utils в админ-панели и как REST endpoint.
Endpoint: POST /api/v1/utils/extract-jpath
Тело запроса:
| Поле | Тип | Описание |
|---|---|---|
jpath |
string | JsonPath-выражение для вычисления |
from |
object | JSON-документ, к которому применяется выражение |
Пример cURL:
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"}
]
}
}'
Ответ:
{
"extract": ["john@example.com", "jane@example.com"]
}
Endpoint намеренно не покрыт SDK — это отладочный helper, а не часть автоматизационного API. SDK (Go/Python/Java) и CLI не содержат специальной обёртки; используйте обычный HTTP POST из вашего языка или страницу Utils → JsonPath Tester в админ-панели.
Отладка выражений
Пример отладочного мока:
{
"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"
}
}
}
}
Известные ограничения
При использовании JsonPath-выражений внутри строковых значений JSON (не как самостоятельное значение поля) действуют следующие ограничения из-за regex-движка интерполяции:
| Возможность | Самостоятельное значение | Внутри строки |
|---|---|---|
Простые пути $.req.user.id |
Работает | Работает |
Индекс массива $.req.items[0] |
Работает | Работает |
Отрицательный индекс $.req.items[-1] |
Работает | НЕ работает |
Wildcard $.req.items[*].name |
Работает | НЕ работает |
Рекурсивный спуск $..email |
Работает | НЕ работает |
Фильтр $.items[?(@.price>100)] |
Работает | НЕ работает |
Fallback-синтаксис || работает только внутри аргументов математических функций:
- Работает:
$.increment($.gS.counter || 0) - НЕ работает как самостоятельное выражение:
$.req.userId || "default"
Неразрешённые выражения возвращают строку ошибки вида "Error: JSONPath '$.req.missing' not found" как в JSON-, так и в XML-ответах. Это касается как самостоятельных значений $.xxx, так и выражений $.xxx, встроенных в строки. Используйте синтаксис || default внутри математических функций (например, $.increment($.gS.counter || 0)), чтобы корректно обрабатывать отсутствующие значения.
Глубина рекурсии ограничена 15 уровнями вложенности JSON-объектов.
Лучшие практики
-
Используйте осмысленные имена в Store:
"extract": { "cStore": { "userId": "$.req.id", "userEmail": "$.req.email", "sessionStartTime": "$.fake.RFC3339" } } -
Используйте
||fallback в математических функциях для обработки отсутствующих значений:$.increment($.gS.counter || 0) $.sum($.gS.price || 0, $.req.tax)Примечание: Синтаксис
||работает только внутри аргументов математических функций ($.increment,$.sum,$.multiply,$.subtract). Он НЕ работает как самостоятельное выражение вроде$.req.user.id || "default-id". -
Используйте фильтры для сложной логики:
$.orders[?(@.status == 'completed' && @.amount > 100)] -
Комбинируйте статические и динамические данные:
{ "message": "Hello $.req.name! Your order #$.fake.UUIDDigit is confirmed", "timestamp": "$.fake.RFC3339" }
XML поддержка
JsonPath выражения также работают внутри XML ответов (SOAP моки):
{
"response": {
"payload": "<GetUserResponse><UserId>$.req.id</UserId><Name>$.fake.FirstName</Name><Email>$.fake.Email</Email></GetUserResponse>"
}
}
Mockarty автоматически экранирует спецсимволы XML (<, >, &, ", ') при подстановке значений в XML строки. Также нормализует пробелы в namespace-ах и атрибутах.
Go Template режим
Помимо JsonPath, Mockarty поддерживает Go Template синтаксис для файловых шаблонов. Загрузите шаблон из файла через поле templateFile:
{
"response": {
"templateFile": "my-template.json"
}
}
Доступные функции внутри Go Template:
| Функция | Описание | Пример |
|---|---|---|
req |
Данные запроса (без аргументов, возвращает объект запроса) | {{(req).user.name}} |
reqHeader |
Данные заголовка (без аргументов, возвращает map заголовков) | {{index (reqHeader) "Authorization"}} |
fake |
Faker данные (без аргументов, возвращает объект faker) | {{(fake).FirstName}} |
mS |
Mock Store (без аргументов, возвращает map хранилища) | {{index (mS) "key"}} |
cS |
Chain Store (без аргументов, возвращает map хранилища) | {{index (cS) "key"}} |
gS |
Global Store (без аргументов, возвращает map хранилища) | {{index (gS) "key"}} |
asJson |
Преобразование в JSON | {{asJson .Request}} |
Важно: Go Template и JsonPath – два разных режима. JsonPath работает в полях
payload(JSON), Go Template работает вtemplateFile.
Используйте это руководство для создания мощных динамических моков с JsonPath!
Смотрите также
- Справочник Faker-функций – все доступные функции для генерации тестовых данных
- Системы хранилищ (Store) – Global, Chain и Mock хранилища для моков с состоянием
- Справочник API – полный REST API, включая endpoint для тестирования JsonPath
- Руководство по веб-интерфейсу – визуальный конструктор моков с поддержкой JsonPath
- Быстрый старт – начните работу с первым динамическим моком