Документация Руководство по JsonPath

JsonPath руководство для Mockarty

Содержание

  1. Что такое JsonPath
  2. Основной синтаксис
  3. Примеры использования
  4. Извлечение данных
  5. Переменные в ответах
  6. Store доступ
  7. Faker интеграция
  8. Сложные примеры

Совет: Примеры кода доступны для 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
  • Проверки условий при мэтчинге моков

Куда записывать выражение

Что нужно сделать Куда поместить выражение Пример
Прочитать поле текущего запроса В поле ответа или правило extract $.req.email
Использовать данные запроса при следующем вызове В extract.cStore или extract.gStore, затем в поле ответа Сохранить $.req.email, позже прочитать $.cS.email
Сгенерировать значение или вычислить результат В поле ответа $.fake.FirstName, $.sum($.req.price, 10)

extract читает пути из входящего запроса. Faker и математические функции используйте в шаблонах ответа. Запись в Store может завершиться после текущего ответа, поэтому только что сохранённое значение читайте при следующем запросе.


Основной синтаксис

Базовые выражения

Выражение Описание Пример
$ Корень документа $.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)
$.divide(expr1, expr2) Деление (expr1 / expr2; деление на ноль даёт 0) $.divide($.req.total, $.req.count)
$.modulo(expr1, expr2) Остаток от деления expr1 / expr2 $.modulo($.req.index, 2)
$.length(expr) Размер значения: число элементов массива, число ключей объекта или число рун строки $.length($.req.items)

Аргументами могут быть:

  • Числовые литералы: $.sum(10, 20)
  • JsonPath выражения: $.sum($.req.a, $.req.b)
  • Store ссылки: $.sum($.gS.total, $.req.amount)
  • Выражения с default: $.increment($.gS.counter || 0) – если значение отсутствует, используется 0

Строковые функции

Преобразуют одно значение, полученное из любого вложенного выражения (поле запроса, faker, store или другая строковая функция).

Функция Описание Пример
$.upper(expr) Привести к верхнему регистру $.upper($.req.code)
$.lower(expr) Привести к нижнему регистру $.lower($.fake.Email)
$.trim(expr) Убрать пробелы в начале и конце $.trim($.req.name)
$.replace(expr, old, new) Заменить все вхождения old на new $.replace($.req.phone, "-", "")
$.substring(expr, start[, end]) Срез по индексу символа (end необязателен) $.substring($.req.code, 0, 4)
$.default(expr, fallback) Использовать fallback, если первое значение пустое $.default($.req.name, "guest")
$.base64encode(expr) Закодировать значение в стандартный base64 $.base64encode($.req.creds)
$.base64decode(expr) Декодировать стандартный base64 (невалидный вход — как есть) $.base64decode($.req.token)
$.urlencode(expr) URL-кодирование (query-эскейпинг) $.urlencode($.req.q)
$.urldecode(expr) URL-декодирование $.urldecode($.req.q)
  • Каждая функция возвращает строку, поэтому их можно вкладывать: $.upper($.trim($.req.code)).
  • Строковые литералы указываются в кавычках ("..." или '...'); всё, что начинается с $., сначала резолвится — можно передавать поля запроса, faker или значения store как аргументы.
  • Если выражение ничего не вернуло, результат — пустая строка (именно это проверяет $.default).
  • $.substring считает символы, а не байты, и обрезает выход за границы — поэтому не падает на коротком значении.

Функция времени

$.now(...) возвращает текущее время с необязательным относительным сдвигом и форматом вывода. В отличие от $.fake-полей дат (случайных), $.now — это реальное «сейчас»: идеально для срока действия токена, меток created/updatedAt или даты на фиксированном расстоянии от сегодня.

Форма Результат
$.now() Текущее время, RFC3339 (UTC), напр. 2026-07-25T14:30:45Z
$.now(30d) Сейчас + 30 дней, RFC3339
$.now(-1h) Сейчас − 1 час, RFC3339
$.now(0, date) Сегодня как 2026-07-25
$.now(7d, unix) (сейчас + 7 дней) в epoch-секундах
$.now(0, "15:04") Сейчас с произвольным Go-layout
  • Сдвиг: единицы s (секунды), m (минуты), h (часы), d (дни), w (недели); можно комбинировать (1d12h) и ставить - для движения в прошлое. Пусто или 0 — ровно сейчас.
  • Формат (пресеты): rfc3339 (по умолчанию), rfc3339nano, date, datetime, time, unix, unixmilli. Любое другое значение трактуется как сырой Go-layout (напр. 2006-01-02).

Примеры использования

Простое извлечение

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": "$.headers.Authorization",
      "contentType": "$.headers['Content-Type']"
    }
  }
}

В правиле extract используйте $.headers. Заголовок с одним значением представлен строкой, с несколькими — массивом; чтобы взять первое значение массива, добавьте [0]. В шаблонах ответа для заголовков используется другой префикс — $.reqHeader из таблицы выше.

Извлечение 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,}$"
    }
  ]
}

Операторы условий (assertAction)

Оператор Совпадает, когда значение… value
equals равно value ожидаемое значение
not_equals не равно value значение для исключения
contains содержит value (подстрока / элемент массива); для числа или логического значения — точное равенство, 100 не содержит 10 подстрока или элемент
not_contains не содержит value (для числа или логического значения — не равно ему) подстрока или элемент
starts_with начинается с value префикс
ends_with заканчивается на value суффикс
is_number является числом (целым или дробным) — (игнорируется)
num_digits состоит только из цифр, и их ровно value количество цифр, напр. 6 для одноразового кода
one_of равно одному из списка список ["open","closed"] или строка через запятую "open, closed"
matches совпадает с регулярным выражением value regex-шаблон
notEmpty / empty непустое / пустое — (игнорируется)
any совпадает всегда (проверка наличия) — (игнорируется)

Операторы starts_with, ends_with, is_number, num_digits и one_of
покрывают частые случаи без регулярных выражений — например, шестизначный
код подтверждения:

{
  "conditions": [
    { "path": "$.otp", "assertAction": "num_digits", "value": 6 }
  ]
}

Переменные в ответах

Использование извлеченных данных

{
  "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

Через extract.gStore можно сохранить поле входящего запроса. Например, тело запроса содержит {"userId":"u-42"}:

{
  "extract": {
    "gStore": {"lastActiveUser": "$.req.userId"}
  }
}

Другой мок в том же пространстве имён сможет прочитать сохранённое значение при следующем вызове:

{
  "response": {
    "payload": {"lastActiveUser": "$.gS.lastActiveUser"}
  }
}

Chain Store

Укажите одинаковый chainId у моков, которым нужны общие данные цепочки. Первый мок сохраняет поля запроса, а в своём ответе использует данные текущего запроса:

{
  "chainId": "user-registration",
  "extract": {
    "cStore": {
      "userId": "$.req.userId",
      "email": "$.req.email"
    }
  },
  "response": {
    "payload": {"userId": "$.req.userId", "status": "registered"}
  }
}

Следующий мок этой цепочки читает сохранённые значения:

{
  "chainId": "user-registration",
  "response": {
    "payload": {"userId": "$.cS.userId", "email": "$.cS.email"}
  }
}

Области видимости и срок хранения описаны в руководстве по Store.


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"
    }
  }
}

Математические операции

Подробные примеры

Счётчик с увеличением

Поместите $.increment в шаблон ответа. Функция увеличивает счётчик в Global Store и возвращает новое значение:

{
  "http": {"route": "/api/counter", "httpMethod": "GET"},
  "response": {
    "payload": {"visits": "$.increment($.gS.visitCount || 0)"}
  }
}

Первый вызов возвращает 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 внутри строк будут автоматически заменены на соответствующие значения.


Сложные примеры

В каждом примере ниже показана одна задача. Добавляйте только те поля, которые нужны вашему клиенту.

Динамический счётчик

Для счётчика запросов используйте пример с увеличением. Одно выражение $.increment(...) обновляет сохранённое значение и возвращает его в ответе.

Цепочка для данных пользователя

Для двух шагов используйте пример Chain Store: первый мок сохраняет userId и email из запроса через extract.cStore, а следующий читает их через $.cS.userId и $.cS.email. Генерируйте новое значение в ответе только тогда, когда оно не должно совпадать с отдельно сохранённым значением.

Обработка заказа

Пусть тело запроса содержит {"orderId":"o-17","quantity":2,"unitPrice":10}. Мок возвращает номер заказа и рассчитанную сумму, а номер сохраняет для последующих запросов:

{
  "id": "process-order",
  "http": {"route": "/api/orders", "httpMethod": "POST"},
  "response": {
    "payload": {
      "orderId": "$.req.orderId",
      "total": "$.multiply($.req.quantity, $.req.unitPrice)"
    }
  },
  "extract": {
    "gStore": {"lastOrderId": "$.req.orderId"}
  }
}

Ответ с данными из Store

При следующем запросе можно прочитать сохранённый номер заказа. $.now() добавит время формирования ответа:

{
  "id": "analytics-report",
  "http": {"route": "/api/analytics/report", "httpMethod": "GET"},
  "response": {
    "payload": {
      "lastOrderId": "$.gS.lastOrderId",
      "generatedAt": "$.now()"
    }
  }
}

Утилиты для работы с JsonPath

Страница утилит – тестер JsonPath

Тестирование JsonPath

Mockarty позволяет проверить JsonPath-выражение на произвольном JSON, не создавая мок: в админ-панели через Utils → Testers → JsonPath либо по REST. Оба пути вычисляют выражение тем же экстрактором, что и ваши моки, — увиденный здесь результат совпадёт с тем, что даст условие мока или $.-подстановка.

В интерфейсе: введите выражение, вставьте JSON-документ — результат появляется по мере ввода. Невалидный документ, неверное выражение и выражение без совпадений сообщают о себе прямо над полем.

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 → Testers → JsonPath в админ-панели.

Отладка выражений

Пример отладочного мока:

{
  "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-объектов.


Лучшие практики

  1. Используйте осмысленные имена в Store:

    "extract": {
      "cStore": {
        "userId": "$.req.id",
        "userEmail": "$.req.email",
        "sessionStartTime": "$.fake.RFC3339"
      }
    }
    
  2. Используйте || fallback в математических функциях для обработки отсутствующих значений:

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

    Примечание: Синтаксис || работает только внутри аргументов математических функций ($.increment, $.sum, $.multiply, $.subtract). Он НЕ работает как самостоятельное выражение вроде $.req.user.id || "default-id".

  3. Используйте фильтры для сложной логики:

    $.orders[?(@.status == 'completed' && @.amount > 100)]
    
  4. Комбинируйте статические и динамические данные:

    {
      "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!


Смотрите также