Swagger/OpenAPI генерация для C++: обзор инструментов и библиотек

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Swagger/OpenAPI генерация для C++: обзор инструментов и библиотек

Современная разработка серверных приложений на C++ редко обходится без REST API. Спецификация OpenAPI (ранее известная как Swagger) стала промышленным стандартом для описания интерфейсов взаимодействия между клиентом и сервером. Однако ручное написание кода для обработки запросов, валидации данных и генерации ответов — трудоёмкий и подверженный ошибкам процесс. К счастью, экосистема C++ предлагает несколько зрелых решений для автоматической генерации кода по OpenAPI-спецификации. В этой статье мы разберём основные инструменты, их сильные стороны и приведём практические примеры.

1. OpenAPI Generator (openapi-generator.tech)

Самый популярный универсальный генератор кода для десятков языков, включая C++. Поддерживает OpenAPI 3.0 и 3.1. Позволяет сгенерировать как серверный код (C++ REST SDK / cpprestsdk, Pistache, Restbed), так и клиентский код.

Установка

npm install @openapitools/openapi-generator-cli -g
# или через Docker:
docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate \
  -i /local/petstore.yaml \
  -g cpp-restsdk \
  -o /local/out/cpp-client

Пример генерации клиента на cpprestsdk

Допустим, у вас есть файл petstore.yaml с описанием API для зоомагазина. После генерации вы получите готовые классы:

#include "ApiClient.h"
#include "PetApi.h"

int main() {
    auto client = std::make_shared<ApiClient>();
    PetApi api(client);

    api.getPetById(1).then([](std::shared_ptr<Pet> pet) {
        std::cout << "Pet name: " << pet->getName() << std::endl;
    }).wait();
    return 0;
}

Плюсы: огромное сообщество, поддержка множества фреймворков, активная разработка.

Минусы: сгенерированный код может быть избыточным, требует ручной донастройки под конкретный фреймворк.

2. oat++ (oatpp.io)

Современный фреймворк для C++ с собственной поддержкой OpenAPI 3.0. В отличие от OpenAPI Generator, oat++ не генерирует код из спецификации, а позволяет аннотировать уже написанные эндпоинты и автоматически экспортировать OpenAPI-спецификацию.

Пример аннотации эндпоинта

ENDPOINT("GET", "/pets/{petId}", getPetById) {
    auto dto = PetDto::createShared();
    dto->id = request->getPathVariable("petId");
    dto->name = "Rex";
    dto->status = "available";
    return createDtoResponse(Status::CODE_200, dto);
}

// Описание DTO
DTO(PetDto, 
    FIELD(Int32, id, "id"),
    FIELD(String, name, "name"),
    FIELD(String, status, "status")
);

После этого oat++ автоматически сгенерирует openapi.json в рантайме. Для статической генерации используется утилита oatpp-swagger.

Плюсы: нативный подход, единый фреймворк, отличная документация, встроенная поддержка Swagger UI.

Минусы: требует использования oat++ целиком, не подходит для уже существующих проектов на других фреймворках.

3. Drogon (drogon.org)

Высокопроизводительный асинхронный веб-фреймворк для C++17/20. Включает модуль drogon_ctl для генерации скелета проекта и плагин drogon::OpenApiPlugin для автоматической генерации документации OpenAPI 3.0.

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

#include <drogon/drogon.h>
using namespace drogon;

int main() {
    app().registerController(std::make_shared<PetController>());
    app().addPlugin("drogon::OpenApiPlugin", {
        {"title", "Pet Store API"},
        {"version", "1.0.0"}
    });
    app().run();
}

Контроллер с автодокументированием:

class PetController : public HttpController<PetController> {
public:
    METHOD_LIST_BEGIN
        ADD_METHOD_TO(PetController::getPetById, "/pets/{petId}", Get);
    METHOD_LIST_END

    void getPetById(const HttpRequestPtr& req,
                    std::function<void(const HttpResponsePtr&)>&& callback,
                    int petId) const {
        Json::Value pet;
        pet["id"] = petId;
        pet["name"] = "Rex";
        pet["status"] = "available";
        auto resp                    

Рекомендаций