OpenAPI и Swagger на собеседовании системного аналитика

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Карьерник — Duolingo для аналитиков: 10 минут в день тренируй SQL, Python, A/B, статистику, метрики и ещё 3 темы собеса. 1500+ вопросов в Telegram-боте. Бесплатно.

Зачем спрашивают на собесе SA

OpenAPI — стандарт описания REST API. Все интеграции в современной разработке проходят через него. На собесе SA обязательно: «как описать новый эндпоинт в OpenAPI», «как ввести reusable schema», «чем 3.1 отличается от 3.0».

Главная боль без понимания — SA пишет в Word «эндпоинт принимает JSON с user_id» и потом разработчик и команда интеграции переопрашивают друг друга, пишут отдельные json-схемы, всё ломается на проде.

OpenAPI vs Swagger — терминология

OpenAPI Specification (OAS) — спецификация формата описания REST API. Текущая версия — 3.1.0 (2021).

Swagger — историческое название (до версии 2.0). С 2016 проект переименован в OpenAPI, но термин «Swagger» остался в тулинге:

  • Swagger UI — веб-интерфейс для документации.
  • Swagger Codegen — кодогенерация клиентов / серверных стабов.
  • Swagger Editor — онлайн-редактор YAML.

Сегодня правильно говорить «описание в OpenAPI», но «Swagger UI» — нормально.

OpenAPI 3.1 vs 3.0:

  • 3.1 совместим с JSON Schema (можно использовать if/then/else, $dynamicRef).
  • Появился webhook блок (формальное описание webhook'ов).
  • Удалён nullable: true (используй type: [string, "null"]).
  • examples теперь стандартизованы.

Структура спецификации

Файл OpenAPI — YAML или JSON. Корневые секции:

openapi: 3.1.0

info:
  title: Orders API
  version: 1.2.0
  description: API для управления заказами

servers:
  - url: https://api.example.com/v1

tags:
  - name: orders
    description: Заказы

paths:
  /orders: { ... }
  /orders/{id}: { ... }

components:
  schemas: { ... }
  parameters: { ... }
  responses: { ... }
  securitySchemes: { ... }

security:
  - bearerAuth: []

Paths и operations

Каждый путь — объект с операциями (get/post/put/patch/delete/head/options).

paths:
  /orders/{id}:
    get:
      summary: Получить заказ по ID
      operationId: getOrder
      tags: [orders]
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '404':
          description: Не найден
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

parameters in:

  • path — в URL (/orders/{id}).
  • query?status=paid.
  • header — заголовок запроса.
  • cookie — cookie.

Body для POST/PUT:

post:
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/CreateOrderRequest'

Operations должны иметь operationId — уникальный, kebab или camelCase. По нему codegen генерирует имена методов клиента.

Components: schemas, parameters, responses

Reusable элементы. Не повторять — выносить в components.

components:
  schemas:
    Order:
      type: object
      required: [id, status, amount]
      properties:
        id:
          type: integer
          format: int64
        status:
          type: string
          enum: [pending, paid, shipped, cancelled]
        amount:
          type: number
          format: decimal
        items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        created_at:
          type: string
          format: date-time

    Error:
      type: object
      required: [code, message]
      properties:
        code: { type: string }
        message: { type: string }
        details: { type: object }

  parameters:
    LimitParam:
      name: limit
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 20

  responses:
    Unauthorized:
      description: Не авторизован
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

Использование:

paths:
  /orders:
    get:
      parameters:
        - $ref: '#/components/parameters/LimitParam'
      responses:
        '401':
          $ref: '#/components/responses/Unauthorized'

Полезные форматы:

  • int32, int64 — числа.
  • date, date-time — даты.
  • uuid, email, uri.
  • binary, byte (base64).
  • password — hint для UI.
Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Security: bearer, apiKey, oauth2

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key

    oauth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://example.com/oauth/authorize
          tokenUrl: https://example.com/oauth/token
          scopes:
            read:orders: Чтение заказов
            write:orders: Создание/изменение заказов

security:
  - bearerAuth: []

Можно переопределить на уровне операции:

paths:
  /public/health:
    get:
      security: []   # без авторизации

Или потребовать конкретные scope:

post:
  security:
    - oauth2: [write:orders]

Версионирование и эволюция

Где указывать версию:

  • В URL: /v1/orders (наиболее распространено).
  • В header: Accept: application/vnd.api.v1+json.
  • В query: /orders?version=1 (некрасиво, не рекомендуется).

В OpenAPI версия указывается в info.version (semver: 1.2.3). Но это версия документа, не API — обновляется при каждой правке схемы.

Backward-compatible изменения:

  • Добавить новый optional параметр.
  • Добавить новое поле в response.
  • Добавить новый эндпоинт.
  • Расширить enum (если клиенты тестируют unknown).

Breaking changes:

  • Убрать поле / параметр.
  • Сделать optional → required.
  • Сменить тип.
  • Удалить значение из enum.

При breaking change — повышаем major версию (v1v2), деплоим параллельно, постепенно мигрируем клиентов, объявляем deprecation period (обычно 6-12 месяцев).

deprecated: true — поле / эндпоинт помечен как устаревший:

get:
  deprecated: true
  description: Используйте /v2/orders/{id}

Swagger UI покажет вычеркнутым.

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

Не использовать $ref. Дублирование схем. Меняешь в одном месте — забываешь в другом.

Забыть required. Без него все поля optional. На сервере — null pointer, на клиенте — undefined.

Нет схем ошибок. Документ описывает только happy path. Разработчик не знает, что вернёт API при ошибке валидации.

Использовать generic типы. payload: object без структуры — бесполезная документация.

Versioning только в URL без deprecation. Клиенты ломаются молча.

Не указывать operationId. Codegen берёт path + method — получаются страшные имена.

Confidential данные в description. Не пиши «использовать тестовый ключ XXX-YYY» — публикуется в Swagger UI всем.

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

Не валидировать. OpenAPI можно проверить через spectral lint — поймает мелкие ошибки до билда.

Связанные темы

FAQ

Где писать спецификацию — в коде или отдельно?

Два подхода: design-first (сначала OpenAPI YAML, потом код) и code-first (генерация YAML из аннотаций кода). Design-first лучше для команд с SA, code-first — для backend-only команд. На собесе SA ожидают design-first.

Как тестировать API по OpenAPI?

Dredd, Schemathesis — генерят запросы по схеме и проверяют ответы. Postman импортирует OpenAPI и создаёт коллекции.

OpenAPI описывает GraphQL?

Нет. OpenAPI — для REST. Для GraphQL — SDL (Schema Definition Language). gRPC — Protobuf .proto файлы.

Что такое discriminator в OAS?

Поле, которое говорит, какая именно схема (subtype) используется в полиморфном объекте.

oneOf:
  - $ref: '#/components/schemas/Cat'
  - $ref: '#/components/schemas/Dog'
discriminator:
  propertyName: pet_type

Можно ли описать webhooks в OpenAPI?

В 3.1 — да, через корневую секцию webhooks. В 3.0 — только через хак (callbacks внутри операции).

Это официальная информация?

Нет. Статья основана на спецификации OpenAPI 3.1 (https://spec.openapis.org/oas/v3.1.0) и документации Swagger.


Тренируйте системный анализ — откройте тренажёр с 1500+ вопросами для собесов.