Стандартный формат ответа JSON API?

Существуют ли стандарты или лучшие практики для структурирования ответов JSON из API? Очевидно, что данные каждого приложения различны, так что меня это не касается, а, скорее, "шаблон ответа", если хотите. Пример того, что я имею в виду:

Успешный запрос:

{
  "success": true,
  "payload": {
    /* Application-specific data would go here. */
  }
}

Неудачный запрос:

{
  "success": false,
  "payload": {
    /* Application-specific data would go here. */
  },
  "error": {
    "code": 123,
    "message": "An error occurred!"
  }
}

Ответ 1

Да, есть пара стандартов (хотя и с определенными свободами в определении стандарта):

  1. JSON API - JSON API охватывает также создание и обновление ресурсов, а не только ответы.
  2. JSend - Простой и, вероятно, то, что вы уже делаете.
  3. OData JSON Protocol - очень сложный.
  4. HAL - как OData, но стремится быть как HATEOAS.

Есть также форматы описания JSON API:

  • развязность
    • Схема JSON (используется Swagger, но вы можете использовать его отдельно)
  • WADL в JSON
  • RAML
  • HAL, потому что HATEOAS в теории самоописывает себя.

Ответ 2

Руководство по Google JSON

Возвращение успешного ответа data

{
  "data": {
    "id": 1001,
    "name": "Wing"
  }
}

Ошибка возврата ответа error

{
  "error": {
    "code": 404,
    "message": "ID not found"
  }
}

и если ваш клиент JS, вы можете использовать if ("error" in response) {}, чтобы проверить, есть ли ошибка.

Ответ 3

Я предполагаю, что стандарт де-факто действительно не появился (и, возможно, никогда). Но независимо от того, вот мое взятие:

Успешный запрос:

{
  "status": "success",
  "data": {
    /* Application-specific data would go here. */
  },
  "message": null /* Or optional success message */
}

Неудачный запрос:

{
  "status": "error",
  "data": null, /* or optional error payload */
  "message": "Error xyz has occurred"
}

Преимущество: одинаковые элементы верхнего уровня как в случае успеха, так и в случае ошибки

Недостаток: нет кода ошибки, но если вы хотите, вы можете изменить статус на код (успех или неудача), или вы можете добавить еще один элемент верхнего уровня с именем "код".

Ответ 4

Предполагая, что вы задаете вопрос о дизайне веб-сервисов REST и точнее о успехе/ошибке.

Я думаю, что есть 3 разных типа дизайна.

  • Используйте только код состояния HTTP, чтобы указать, была ли ошибка, и попытайтесь ограничить себя стандартными (обычно это должно быть достаточно).

    • Плюсы: это стандарт, независимый от вашего api.
    • Минусы: меньше информации о том, что на самом деле произошло.
  • Используйте статус HTTP + json body (даже если это ошибка). Определите единую структуру для ошибок (например: код, сообщение, причину, тип и т.д.) И используйте ее для ошибок, если это будет успешным, тогда просто верните ожидаемый ответ json.

    • Плюсы: по-прежнему стандартный, поскольку вы используете существующие коды состояния HTTP, и вы возвращаете json, описывающий ошибку (вы предоставляете больше информации о том, что произошло).
    • Минусы: выход json будет меняться в зависимости от ошибки или успеха.
  • Забудьте о статусе http (например: всегда статус 200), всегда используйте json и добавьте в корневой адрес ответ boolean responseValid и объект ошибки (код, сообщение и т.д.), который будет заполнен, если это ошибка, иначе будут заполнены другие поля (успех).

    • Плюсы: клиент имеет дело только с телом ответа, который является json-строкой и игнорирует статус (?).

    • Минусы: менее стандартный.

Вам решать:)

В зависимости от API я бы выбрал 2 или 3 (предпочитаю 2 для json rest apis). Еще одна вещь, которую я испытал при разработке REST Api, - это важность документации для каждого ресурса (url): параметры, тело, ответ, заголовки и т.д. + Примеры.

Я также рекомендовал бы использовать jersey (реализация jax-rs) + genson (java/json databinding library). Вам просто нужно отказаться от genson + jersey в вашем пути к классам, и json автоматически поддерживается.

EDIT:

  • Решение 2 сложнее всего реализовать, но преимущество заключается в том, что вы можете прекрасно обрабатывать исключения, а не только бизнес-ошибки, начальные усилия важнее, но вы выигрываете в долгосрочной перспективе.

  • Решение 3 легко реализовать как на стороне сервера, так и на стороне клиента, но это не так приятно, поскольку вам придется инкапсулировать объекты, которые вы хотите вернуть в объекте ответа, содержащие также ошибку responseValid +.

Ответ 5

Я не буду так самоуверен, что утвержу, что это стандарт, поэтому я буду использовать форму "Я предпочитаю".

Я предпочитаю краткий ответ (при запросе списка/статей мне нужен массив статей JSON).

В моих проектах я использую протокол HTTP для отчета о состоянии, 200 возвращает только полезную нагрузку.

400 возвращает сообщение о том, что было не так с запросом:

{"message" : "Missing parameter: 'param'"}

Возвращает 404, если модель/контроллер/URI не существует

Если на моей стороне была ошибка при обработке, я возвращаю 501 сообщение:

{"message" : "Could not connect to data store."}

Из того, что я видел, достаточно много структур REST-ish, как правило, в этом направлении.

Обоснование

Предполагается, что JSON является форматом полезной нагрузки, это не протокол сеанса. Вся идея многословных полезных данных сеанса происходит из мира XML/SOAP и различных ошибочных вариантов, которые создавали эти раздутые проекты. После того, как мы поняли, что все это было массивной головной болью, весь смысл REST/JSON заключался в том, чтобы KISS его и придерживаться HTTP. Я не думаю, что в JSend есть что-то дистанционно стандартное, и особенно не с более подробным из них. XHR будет реагировать на HTTP-ответ, если вы используете jQuery для своего AJAX (как и большинство из них), вы можете использовать обратные вызовы try/catch и done()/fail() для захвата ошибок. Я не вижу, как инкапсуляция отчетов о состоянии в JSON более полезна.

Ответ 6

Ниже приводится индекс json format, использующий

{
    "meta": {
         "error_type": "OAuthException",
         "code": 400,
         "error_message": "..."
    }
    "data": {
         ...
    },
    "pagination": {
         "next_url": "...",
         "next_max_id": "13872296"
    }
}

Ответ 8

Для чего это стоит, я делаю это по-другому. У успешного вызова есть только объекты JSON. Мне не нужен объект JSON более высокого уровня, который содержит поле успеха, указывающее true и поле полезной нагрузки, которое имеет объект JSON. Я просто возвращаю соответствующий объект JSON с 200 или любым, что подходит в диапазоне 200 для статуса HTTP в заголовке.

Однако, если есть ошибка (что-то из семейства 400), я возвращаю хорошо сформированный объект ошибки JSON. Например, если клиент выполняет POSTing пользователя с адресом электронной почты и номером телефона, и один из них неверен (т.е. Я не могу вставить его в мою базовую базу данных), я верну что-то вроде этого:

{
  "description" : "Validation Failed"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Invalid phone number."
  } ],
}

Важные биты здесь состоят в том, что свойство "field" должно соответствовать полю JSON, которое не может быть проверено. Это позволяет клиентам точно знать, что пошло не так с их запросом. Кроме того, "сообщение" находится в локали запроса. Если оба "emailAddress" и "phoneNumber" были недопустимыми, массив "errors" будет содержать записи для обоих. Ответный орган JSON 409 (конфликт) может выглядеть следующим образом:

{
  "description" : "Already Exists"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Phone number already exists for another user."
  } ],
}

С кодом статуса HTTP и этим JSON у клиента есть все, что им нужно, чтобы ответить на ошибки детерминированным способом и не создает новый стандарт ошибок, который пытается завершить замену кодов состояния HTTP. Обратите внимание, что это происходит только в диапазоне 400 ошибок. Для чего-либо в диапазоне 200 я могу просто вернуть все, что подходит. Для меня это часто HAL-подобный объект JSON, но здесь это не имеет особого значения.

Единственное, что я подумал о добавлении, - это числовой код ошибки либо в записях массива "ошибки", либо в корне самого объекта JSON. Но пока нам это не нужно.

Ответ 9

Они не согласны с остальными форматами ответов API-интерфейсов крупных программных гигантов - Google, Facebook, Twitter, Amazon и других, хотя в приведенных выше ответах было приведено много ссылок, где некоторые люди пытались стандартизировать формат ответов.

Поскольку потребности API могут различаться, очень сложно привлечь всех и согласиться на какой-либо формат. Если ваши API используют миллионы пользователей, зачем менять формат ответа?

Ниже приводится мое мнение о формате ответов, вдохновленном Google, Twitter, Amazon и некоторыми публикациями в Интернете:

https://github.com/adnan-kamili/rest-api-response-format

Swagger файл:

https://github.com/adnan-kamili/swagger-sample-template

Ответ 10

Точка JSON заключается в том, что она полностью динамична и гибка. Согните его по любому желанию, потому что это всего лишь набор сериализованных объектов JavaScript и массивов, внедренных в один node.

Какой тип корневого каталога зависит от вас, то, что он содержит, зависит от того, передаете ли вы метаданные вместе с ответом, независимо от того, установлен ли тип mime на application/json или оставьте его поскольку text/plain зависит от вас (пока вы знаете, как обращаться с крайними случаями).

Создайте легкую схему, которая вам нравится.
Лично я обнаружил, что отслеживание аналитики и поддержка mp3/ogg и изображений, а также текстовые сообщения и сетевые пакеты для онлайн-игр, а также сообщения в блогах и комментарии к блогу all имеют < сильные > очень разные требования с точки зрения того, что отправлено и что получено, и как они должны потребляться.

Итак, последнее, что я хотел бы, когда все это делаю, - попытаться заставить каждого соответствовать одному и тому же стандарту шаблона, который основан на XML2.0 или somesuch.

Тем не менее, многое можно сказать о том, чтобы использовать схемы, которые имеют смысл для вас и хорошо продуманы.
Просто прочитайте некоторые ответы API, обратите внимание на то, что вам нравится, критикуйте то, что вы этого не сделаете, напишите эти критические замечания и поймите, почему они потирают вас по-другому, а затем подумайте о том, как применять то, что вы узнали, к тому, что вам нужно.

Ответ 11

JSON-RPC 2.0 определяет стандартный формат запросов и ответов и является глотком свежего воздуха после работы с REST API.

Ответ 12

Лучший ответ для веб-API, который может легко понять разработчики мобильных приложений.

Это для ответа "Успех"

{  
   "ReturnCode":"1",
   "ReturnMsg":"Successfull Transaction",
   "ReturnValue":"",
   "Data":{  
      "EmployeeName":"Admin",
      "EmployeeID":1
   }
}

Это для ответа "Ошибка"

{
    "ReturnCode": "4",
    "ReturnMsg": "Invalid Username and Password",
    "ReturnValue": "",
    "Data": {}
}

Ответ 13

Предлагаемая базовая структура выглядит отлично, но объект ошибки, как он определен, слишком ограничен. Часто для выражения проблемы нельзя использовать одно значение, а вместо этого нужна цепочка проблем и причин.

Я провел небольшое исследование и обнаружил, что наиболее распространенным форматом для возврата ошибки (исключения) является структура этой формы:

{
   "success": false,
   "error": {
      "code": "400",
      "message": "main error message here",
      "target": "approx what the error came from",
      "details": [
         {
            "code": "23-098a",
            "message": "Disk drive has frozen up again.  It needs to be replaced",
            "target": "not sure what the target is"
         }
      ],
      "innererror": {
         "trace": [ ... ],
         "context": [ ... ]
      }
   }
}

Это формат, предложенный стандартом OASIS для данных OASIS OData, и он, кажется, является наиболее стандартным вариантом, однако пока не наблюдается высоких показателей принятия какого-либо стандарта. Этот формат соответствует спецификации JSON-RPC.

Вы можете найти полную библиотеку с открытым исходным кодом, которая реализует это по адресу: Mendocino JSON Utilities. Эта библиотека поддерживает объекты JSON, а также исключения.

Подробности обсуждаются в моем блоге об обработке ошибок в JSON REST API.