Формат параметров запроса и ответа в REST API. Для выборки связанных данных одним запросом. Спецификация является рекомендательной и не обязывает реализовывать все опции. Опции отмечены по уровню востребованности .
Запрос
fields
— запрашиваемые данные.- По умолчанию
- Все свойства
*
- Выборочные свойства
prop1, prop2(prop3)
- Свойства списка
items(prop), count
- Исключение свойств
!prop
- Зависимость от типа объекта
prop(type1:prop1, type2:prop2)
- Рекурсивные шаблоны
comments(text, children(^))
search
— условие выборки.- Равенство значению
search[prop]=value
- Вхождение в строку
search[prop]=*value
- Вхождение с сначала строки
search[prop]=^value
- Полнотекстовый поиск
search[prop]=~value
- Регулярное выражение
search[prop]=/value/
- Неравенство значению
search[prop]=!value
- Равенство значению со спец. символами
search[prop]="value-with!~^*<>;|
- Больше, меньше
search[prop]=>value
,search[prop]=<value
- Больше или равно, меньше или равно
search[prop]=>>value
,search[prop]=<<value
- Диапазон значений
search[prop]=min;max
- Интервал значений
search[prop]=min~max
- Вне диапазона значений
search[prop]=!min;max
- Вне интервала значений
search[prop]=!min~max
- Отсутствие свойства или значения
search[prop]=null
- Выполнение любого условия
search[prop]=exp1|exp2
- Выполнение всех условий
search[prop]=exp1&exp2
- Не выполнение любого условия
search[prop]=!exp1|!exp2
- Не выполнение всех условий
search[prop]=!exp1&!exp2
- Условие по вложенному свойству
search[prop1.prop2]=value
- Условие фильтрации свойства
search.prop1[prop]=value
- Равенство значению
sort
— сортировка.- По одному полю
sort=prop
- Обратная сортировка
sort=-prop
- По вложенному свойству
sort=prop1.prop2.prop3
- По нескольким свойствам
sort=-prop1, prop2
- Сортировка в множественном свойстве
sort.prop1 = prop2
- По одному полю
limit
— ограничение количества.- По умолчанию
- Не больше указанного
limit=10
- Без ограничений
limit=*
- В множественом свойстве
limit.prop=10
skip
— с какой позиции ограниченное количество.- С указанной
skip=10
- В множественом свойстве
skip.prop=10
- С указанной
depth
— ограничение вложенности.- По умолчанию
- Не больше указанного
depth.prop=10
- Без ограничений
depth.prop=*
lang
— язык при мультиязычности.- По умолчанию
- Для всех свойств
lang=en
- Все варианты языков
lang=*
- Несколько языков
lang=en, ru
- Для одного свойства
lang.prop=en
Ответ
result
— успешный результат.- Один объект
{"result":{}}
- Список объектов
{"result":{"items":[]}}
- Один объект
error
— ошибки запроса.- Общая информация
{"error":{"code":"400", "message":"", "data":{}}}
- Ошибки в полях
{"error":{"data":{"fields:[]}}}
- Общая информация
Спецификация определяет query параметры запроса для указания что выбрать, с каким условием, сортировкой и ограничением. Параметры опциональные, допускается их переименование и применение дополнительных. URL запроса любой.
GET /objects?fields=name,author(age)&search[author.age]=18;30&sort=-name&limi=10&skip=0&lang=ru
Структура запрашиваемых данных — названия свойств и отношений объекта, которые нужно получить одним запросом.
Альтернативные названия: data, props, select, structure
В классическом REST API структура ответа жестко определяется сервером. Клиент получает лишние
данные, либо сталкивается с нехваткой нужных. Например, связанные объекты нужно запрашивать
отдельными запросами, имея их идентификатор. Обработка параметра fields
решает эту проблему.
Одним запросом можно выбрать все необходимые связанные данные и не запрашивать лишние.
Параметр fields
реализуется не только в GET запросах, но и в запросах создания, изменения и
удаления объектов. В каждом запросе, который способен вернуть объект.
Предполагается, что в fields
указываются свойства объектов. Но если реализовать api роут для
доступа к корню всех данных, то в fields
будут указываться названия коллекций (типов, таблиц, множеств).
В этом случаи, действительно, одним запросом можно выбрать абсолютно все необходимые данные.
GET /root?fields=users(email,phone), news(title, text), categories(name, rating)
Формат параметра search
позволяет на каждое свойство определить условие выборки (фильтра).
Если параметр fields
не указан или равен пустой строке, то сервер возвращает минимальный набор
данных исходя из своих настроек. Обычно возвращается только идентификатор объекта.
{
"result": {
"id": 1
}
}
Символ *
указывает на выбор всех непосредственных свойств объекта. С учётом их доступности на
сервере. Выборка свойств связанных объектов не выполняется — только их внешние ключи.
{
"result": {
"id": 1,
"type": "some",
"name": "Test object",
"status": "new",
"profile": {
"phone":"+79996665544",
"avatar":{
"id": 23,
"type": "file"
}
}
}
}
В данном примере profile
является вложенным объектом (не отношением), а аватарка является
отношением на объект с типом file
и идентификатором 23
. Для выборки свойств аватарки нужно их явно
указать в fields
.
Конкретные свойства объекта указываются через запятую. Допустимы пробелы, переводы строк, табы. Для вложенности используются круглые скобки. Идентификатор объекта возвращается всегда (свойства по умолчанию).
GET /some/1?fields=name, profile(avatar(url, extension), prop3)
{
"result": {
"id": 1,
"name": "Test object",
"profile": {
"avatar": {
"url": "/uploads/1928-212/5c2f3ed1fee590496c63759f.png",
"extension": "png"
},
"prop3": null
}
}
}
Если запрашиваемое свойство у объекта отсутствует, то в ответе оно будет с null значением. То есть в любом случаи свойство возвращается.
Свойства списка. Если сервер возвращает список объектов, то fields
применяется к каждому объекту списка.
Чтобы одним запросом запросить свойства самого списка, например общее количество объектов,
удовлетворяющих условию без ограничений, то запрашиваемые свойства нужно вложить в items
и через
запятую указывать свойства списка. Структура ответа будет консистентна запросу.
GET /some/1?fields=items(name, profile(phone)), count
{
"result": {
"items": [
{
"id": 1,
"name": "Test object",
"profile": {
"phone":"+79996665544"
}
},
{
"id": 3,
"name": "Test object 3",
"profile": {
"phone":"+79996665555"
}
}
],
"count": 105
}
}
Какие именно свойства есть у списка, зависит от реализации АПИ, по умолчанию доступен count
.
Можно реализовать выборку средних, минимальных значений, но чаще функции агрегации реализуются
отдельными запросами.
Исключение свойства. Если у объекта много свойств и только одно из них не требуется возвращать, то вместо перечисления длинного списка возвращаемых свойств с исключением одного, можно применить отрицание свойства.
Сначала указывается, что нужны все свойства символом *
, далее через запятую свойства, которое исключить
с символом !
. Если не указать *
, то исключение будет из свойств, возвращаемых по умолчанию.
GET /some/1?fields=*, !name, !profile
{
"result": {
"id": 1,
"type": "some",
"status": "new"
}
}
Зависимость от типа объекта. В списке запрашиваемых объектов одно и то же отношение может отличаться типом связанного объекта.
Например, "объекты избранного" могут ссылаться на пользователя, статью, товар и прочие типы объектов.
Соответственно, доступные свойства отношения будут различаться. Если в fields указать свойства
пользователя, то для статьи они окажутся null
.
Чтобы не возвращать null
, нужно в fields указывать свойства для конкретного типа объекта.
Перед именем свойства указывается название типа объекта, разделяя двоеточием :
GET /favorites?fields=relative(user:surname, product:price(value, unit), product:title)
{
"result": {
"items": [
{
"_id": "5c2f3ed1fee590496c93779d",
"relative": {
"_id": "5c2f3ed1fee590496c935678",
"_type": "user",
"surname": "UserSurname"
}
},
{
"_id": "5c2f3ed1fee590496c93778f",
"relative": {
"_id": "5c2f3ed1fee590496c935608",
"_type": "product",
"price": {
"value": 100,
"unit": "USD"
},
"title": "ProductTitle"
}
}
]
}
}
Тип можно указывать для любых свойств, не только свойств отношений. Например, пользователи могут
отличаться типом за счёт наследования. В одном списке будут админы, менеджеры и другие типы
пользователей с различными свойствами. Уместно применять типизацию в fields
для выборки
исключительных свойств, например, админа или менеджера.
Рекурсивные шаблоны. Символом ^
указывается ссылка на перечень полей уровнем выше скобки.
Используется для выборки рекурсивных отношений (иерархий). Например, у каждого комментария есть
свойство children с вложенными комментариями, у которых тоже есть вложенные комментарии.
Запрос без ^
выглядел бы так:
GET /news?fields=text, comments(text, children(text, children(text, children(text, children))
Примером выше описана выборка на три уровня вложеннности, но вложенность может быть гораздо больше. Чтобы определить поля на любой уровень вложенности применяется ссылка на шаблон полей.
GET /news?fields=text, comments(text, children(^))
Ссылка относительная. Чтобы сделать ссылку на два и более уровней выше (на шаблон за второй скобкой),
указывается соответствующее количество символов ^
.
GET /product?fields=title, brand(name, products(title, brand(name, products()))
GET /product?fields=title, brand(name, products(^^))
Условие фильтрации запрашиваемых данных.
Альтернативные названия: filter, cond, where
Параметром search
указываются условия на свойства искомых объектов. Условием может быть равенство
значению, вхождение в диапазон, перечень значений и другие. Допустимо указывать виртуальные свойства
(поля), по которым формируются сложные условия на стороне бэкенда.
Параметром указывается множество условий на разные поля. Названия полей в квадратных скобок. Формат не определяет как логически все условия будут соединены — через И, ИЛИ, НЕ. Зависит от реализации сервера. Обычно условия соединяются через И. На усмотрение сервера конкретные условия объединять в соответствии с задачами АПИ.
Параметром search
не определяются все возможные условия, в ином случаи он станет слишком сложным
для использования и интерпретации сервером.
Равенство значению. Строке, числу, дате, булеву. Если сервером не реализуются шаблоны условий, то в зависимости от поля и задач проекта, условие равенства может быть не строгим, например, проверятся вхождение в сроку.
Вхождение в строку с любой позиции.
Вхождение в строку от начала. Если строка value
короче значения свойства, то условие не выполняется.
Полнотекстовый поиск. value
может иметь дополнительные спец. символы, которые используются
поисковым движком.
Регулярное выражение. Проверка строкового свойства на соответствие регулярному выражению.
Неравенство значению. Для любых типов значений.
Равенство значению со спец. символами. Если value
начинается с двойной кавычки, то последующие
спец. символы не интерпретируются. Выполняется условие равенства значению.
Больше, меньше указанного значения. Для чисел и дат.
Больше или равно, меньше или равно. Так как символ равенства невозможно применить из-за особенностей
URL формата, равенство задаётся двойным символом >>
или <<
. Для чисел и дат.
Вхождение в диапазон чисел или дат. Больше или равно min и меньше или равно max.
GET /products?search[price]=100;200 // Цена в диапазоне от 100 до 200 включительно
Вхождение в интервал чисел или дат. Between в выборках - больше min и меньше max.
Вне диапазона чисел или дат.
Вне интервала чисел или дат.
Отсутствие свойства или значения у свойства.
Выполнение любого условия. Например, перечисление допустимых значений, шаблонов строк, диапазонов чисел и других условий, поддерживаемых сервером.
Выполнение всех условий. Имеет смысл для нестрогих условий.
GET /some?search[prop] = *горо&*Москва
Не выполнение любого условия.
Не выполнение всех условий.
Условие по вложенному свойству (отношению). Путь на вложенное свойство через точку. Разделение точкой зарезервировано для указания пути на свойство. Формат не обязывает применять путь на свойство, если сервер может по другому именованию построить условие выборки из базы.
GET /users?search[profile.role.name]=admin // Условие явно по profile.role.name
GET /users?search[roleName]=admin // Сервер "знает", что условие по profile.role.name
Фильтрация множественного свойства.
Условие может быть как на выбираемое множество объектов, так и на конкретное свойство объекта (обычно тоже множественное). Например, у товара множество точек продаж, выбирая сам товар, можем ограничить список точек продаж по определенному условию.
Через точку указывается, к какому свойству применить условие фильтра. Будет отфильтровано само свойство у выбранных объектов.
GET /products?search.stores[title]=*Magnit // Магазины отфильтровать по названию
Сортировка списков.
Альтернативные названия: order
Сортировка по одному свойству по возрастанию. Указывается название свойства. Направление сортировки может задавать сервер, если не предоставляется выбор.
Указание направления сортировки. По убыванию (desc) с символом минус -
перед названием свойства
без пробела. По возрастанию (asc) без символа.
Сортировка по вложенному свойству (вложенного объекта или отношения). Название свойства указывается через точки в виде пути на него.
GET /stores?sort=contacts.address.street // сортировка (магазинов) по улице в адресе контактов
Сортировка по нескольким свойствам. Названия свойств перечисляются через запятую. Допустимы пробельные символы
GET /products?sort=-price,date //Сортировка по убыванию цены и возрастанию даты
Сортировка внутри множественного свойства объекта. Название сортируемого свойства указывается в названии параметра sort, а по какому полю — в значении.
GET /products?sort.stores=title // Свойство магазинов отсортировать по названию магазинов
Ограничение количества возвращаемых объектов в списке.
Альтернативные названия: count, size, length
Если параметр limit
не передан или равен пустой строке, то сервер использует значние по умолчанию
на своё усмотрение, обычно в пределах 100.
Ограничение количества целым числом. Сервер должен вернуть не больше указанного количества. Может вернуть меньше.
Без ограничений выбрать все объекты. Допускается в редких случаях, когда действительно есть необходимость гарантировано получить все объекты.
Ограничение внутри множественного свойства объекта. Название ограничиваемого свойства указывается
в названии параметра limit
через точку.
GET /aritcles?limit.comments=10
Позиция, с которой вернуть ограниченное количество объектов в списке.
По умолчанию skip
равен нулю, сервер возвращает список, начиная с первого объекта.
Альтернативные названия: offset, seek, position
Позиция целым числом. Если позиция больше чем общее количество объектов, то сервер вернут ноль объектов.
Сдвиг внутри множественного свойства объекта. Название свойства указывается
в параметре skip
через точку.
GET /aritcles?skip.comments=10
Ограничение вложенности (глубины) при выборке иерархических структур или рекурсивных связей. Обычно указывается для свойств объекта. Так как вложенная структура образуется выборкой свойств объекта.
Альтернативные названия: level
Если параметр depth
не передан или равен пустой строке, то сервер использует значение по умолчанию
по своему усмотрению. depth
используется только для рекурсивных fields
.
Ограничение максимальной вложенности рекурсивных свойств (связей) целым числом.
Название свойства указывается в параметре depth
через точку.
Выбор страниц 2 уровня и комментариев 4 уровня вложенности
GET /pages?depth.chilren=2&depth.comments=4
Выбрать всю вложенность рекурсивных свойств объекта. Используется с осторожностью, если есть гарантия не зацикленности рекурсивных связей. Например, иерархию комментриев допустимо выбрать сразу всю. Но если выбирается рекурсивное свойство "друг" у пользователя, то на каком-то уровне свойство "друг" может указывать на исходного пользователя и тем самым глубина выборки окажется бесконечной.
Параметр языка для мультиязычных свойств. Для выборки объектов со свойствами в нужном языке.
По подобию параметра lang
можно указывать валюту unit
для цен, версию изменений ver
и другие.
Если параметр lang
не передан или равен пустой строке, то для мультиязычных свойств используется
язык по умолчании. Язык по умолчанию может определяться по установкам аккаунта, заголовкам HTTP или
иначе.
Указание языка для всех мультиязычных свойств объекта. Код языка зависит от специфики проекта.
GET /aritcles?lang=en
{
"title": "Title"
}
Вернуть свойства во всех языках, для которых есть перевод. Структура ответа при этом зависит от особенностей проекта. Предполагается, что мультиязычные свойства получат дополнительную вложенность в виде объекта с ключами, равным кодам языков.
GET /aritcles?lang=*
{
"title": {
"ru": "Заголвоок",
"en": "Title",
"it": "Testata"
}
}
Выбор свойств в указанных языках. Логика аналогична выбору свойств во всех языках.
Указание языка для конкретного свойства объекта.
Название свойства указывается в параметре lang
через точку.
GET /products?lang.stores.title=ru // язык для заголовка магазинов
Любой ответ от сервера возвращается в JSON. Базовая структура ответа едина для всех запросов.
Запрашиваемый объект или скалярное значение возвращается в свойстве result
.
Это необходимо, чтобы любой ответ сервера был валидным JSON.
{
"result": "object or value"
}
Элементы списка возвращаются в свойстве result.items
. В result могут быть дополнительные данные,
например общее количество объектов для пагинации или количество страниц с учётом ограничений выборки.
{
"result": {
"items": ["object or value", "object or value"],
"count": 19822
}
}
Поддержка всех HTTP кодов форматом не определяется. Достаточно различать успешные 2xx и ошибочные запросы 4xxx в соответствии с логикой проекта.
Если сервер возвращает информацию об ошибке, то она прописывается в свойстве error
.
Свойство error.data
содержит подробности об ошибке, например информацию про каждое ошибочное поле
формы.
{
"error": {
"code": "400.42143",
"message": "Some error",
"data": {
"fields": [
{"path": "profile.phone", "message": "Not unique", "code": "unique"},
{"path": "profile.phone", "message": "Bad format", "code": "format"}
]
}
}
}
Предполагается, что у одного поля формы может быть несколько разных ошибок. В предыдущем примере
все ошибки полей возвращаются массивом, а значение path
элементов массива может дублироваться.