Стандарты и сертификаты · тема 3
8

OpenAPI и форматы
данных

Программы обмениваются данными в нескольких стандартных форматах, а сами интерфейсы описывают по стандарту OpenAPI. В главе разобраны описание API, схема данных, формат ошибки и три формата файлов, которые встречаются чаще всего: JSON, CSV и YAML.

Документы
OpenAPI Specification 3.1 · JSON Schema 2020-12 · RFC 9457 · RFC 4180 · YAML 1.2
Уровень
Средний
Где встречается
HTTP API, выгрузки, настройки сервисов
Зачем это знать
Чтобы описать данные так, чтобы их проверяла программа

§1OpenAPI: описание API в файле

OpenAPI Specification — формат описания HTTP API: адреса, методы, параметры, тела запросов, коды и схемы ответов. По файлу строят документацию (Swagger UI, ReDoc), проверяют ответы сервера и генерируют код клиента. До 2016 года спецификация называлась Swagger; теперь это имя носят инструменты.

openapi.yaml, одна операция целиком
openapi: 3.1.0
info:
  title: Service Desk API
  version: 2.5.0
paths:
  /tickets/{ticket_id}:
    get:
      summary: Получить заявку
      operationId: getTicket
      parameters:
        - name: ticket_id
          in: path
          required: true
          schema: {type: integer, minimum: 1}
      responses:
        '200':
          description: Заявка найдена
          content:
            application/json:
              schema: {$ref: '#/components/schemas/Ticket'}
        '404':
          description: Заявки с таким номером нет
          content:
            application/problem+json:
              schema: {$ref: '#/components/schemas/Problem'}
components:
  schemas:
    Ticket:
      type: object
      required: [id, subject, status]
      properties:
        id: {type: integer}
        subject: {type: string, maxLength: 200}
        status: {type: string, enum: [new, in_progress, done]}
        created_at: {type: string, format: date-time}
РазделЧто в нём
openapiверсия спецификации, по которой написан файл
infoназвание и версия самого API
pathsадреса и операции: метод, параметры, тело запроса, ответы
componentsобщие схемы данных, на которые ссылаются через $ref
OpenAPI Specification 3.1.0.
OpenAPI Specification 3.1.0. В версии 3.1 схемы данных совместимы с JSON Schema 2020-12. Подробный разбор — в справочнике «Стандартизация HTTP API».

§2JSON Schema

JSON Schema — язык описания, какой должна быть структура JSON: типы, обязательные поля, допустимые значения. По схеме программа проверяет данные до того, как с ними работать.

schema/ticket.json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "required": ["subject", "email"],
  "properties": {
    "subject": {"type": "string", "minLength": 3, "maxLength": 200},
    "email": {"type": "string", "format": "email"},
    "priority": {"type": "string", "enum": ["low", "normal", "high"], "default": "normal"}
  },
  "additionalProperties": false
}
проверка на Python
from jsonschema import validate, ValidationError

try:
    validate({"subject": "Не работает вход", "priority": "urgent"}, schema)
except ValidationError as e:
    print(e.message)

# 'email' is a required property
Сайт JSON Schema.
Сайт JSON Schema. Действующая редакция — 2020-12. Схемы можно писать и в YAML: структура та же.

§3Описание ошибки по RFC 9457

RFC 9457 «Problem Details for HTTP APIs» задаёт единый вид тела ответа об ошибке. Тип содержимого — application/problem+json.

ответ 422 по RFC 9457
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{
  "type": "https://kursblinovskoy.example/problems/email-taken",
  "title": "Адрес почты уже занят",
  "status": 422,
  "detail": "Ученик с адресом petya@mail.example уже зарегистрирован.",
  "instance": "/signup"
}
ПолеСмысл
typeадрес, который однозначно называет вид ошибки
titleкраткое описание вида ошибки
statusкод ответа HTTP
detailчто случилось в этот раз
instanceк какому запросу относится

RFC 9457 заменил RFC 7807 2016 года; формат совместим.

§4CSV по RFC 4180

CSV — таблица в текстовом файле, по строке на запись. RFC 4180 задаёт правила: поля разделены запятой, первая строка может быть заголовком, поле с запятой, кавычкой или переводом строки заключают в двойные кавычки, а кавычку внутри поля удваивают.

users.csv по RFC 4180
id,full_name,email,comment
1,"Иванова Мария",maria@example.ru,
2,"Петров, Пётр",petr@example.ru,"Сказал: ""позвоните после 18"""
3,"Сидоров Иван",ivan@example.ru,"Две строки
в комментарии"

Excel в русской локали сохраняет CSV с точкой с запятой и в кодировке Windows-1251. Это отступление от RFC 4180; при обмене между программами разделитель и кодировку оговаривают явно. Модуль csv в Python читает файл по правилам RFC 4180, если не указать иное.

чтение и запись на Python
import csv

with open('users.csv', encoding='utf-8', newline='') as f:
    for row in csv.DictReader(f):
        print(row['full_name'], row['email'])

with open('export.csv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.writer(f, delimiter=';')   # для Excel
    writer.writerow(['id', 'full_name'])

§5YAML

YAML 1.2 — формат настроек: Docker Compose, GitHub Actions, OpenAPI. Вложенность задаётся отступами пробелами, табуляция запрещена. YAML 1.2 — надмножество JSON: любой JSON является правильным YAML.

Ловушки YAML

так не надо
country: NO
version: 3.10
port: 08080
password: 12345
так надо
country: "NO"
version: "3.10"
port: 8080
password: "12345"

Старые разборщики по правилам YAML 1.1 читают NO как ложь, 3.10 — как число 3.1, а 08080 — как восьмеричное. Значения, которые должны остаться строками, берут в кавычки.

§6Частые ошибки

Описывать API в документе WordОписание в OpenAPI сверяется с сервером программой; документ Word сверяют вручную, и он отстаёт от кода.
Возвращать ошибку обычным текстомКлиенту нужен машинно читаемый ответ: RFC 9457.
Собирать CSV склейкой строк через запятуюЗапятая или кавычка в данных сломает файл; пишут модулем csv.
Не указывать кодировку CSVФайл из Excel придёт в Windows-1251 с точкой с запятой.
Писать версию в YAML без кавычек3.10 превратится в число 3.1.

§7Проверьте себя

  1. Из каких разделов состоит файл OpenAPI? Где описывают общие схемы?
  2. Что проверяет JSON Schema? Чем поможет additionalProperties: false?
  3. Какие поля описания ошибки задаёт RFC 9457?
  4. Как по RFC 4180 записать поле, в котором есть запятая и кавычка?
  5. Почему в YAML версию 3.10 пишут в кавычках?
APIOpenAPI 3.1paths, components$refSwagger UI, ReDoc
ДанныеJSON Schema 2020-12RFC 9457 — ошибкаproblem+json
ФайлыCSV — RFC 4180"" — кавычка в полеYAML — пробелыстроки в кавычках

Справочник «Стандарты и сертификаты» · глава 8Макаров Максим Николаевич

Кадр