Как создать свой собственный генератор для Swagger Codegen

Swagger Codegen это проект с открытым исходным кодом, с помощью которого можно генерировать клиентские и серверные библиотеки на основе swagger-файлов. По сути разработчик один единственный раз описывает спецификацию своего (или даже чужого) API и одной командой генерирует серверный и клиентский код для любого поддерживаемого языка, экономя человеко-месяцы на разработку.

Какие языки поддерживает Swagger Codegen?

Swagger Codegen 2.3.1 версии позволяет автоматически создавать клиентские библиотеки API (SDK), серверные заглушки и документацию с учетом OpenAPI Spec. В настоящее время поддерживаются следующие языки и фреймворки:

Для клиентских библиотек: ActionScript, Ada, Apex, Bash, C# (.net 2.0, 3.5 or later), C++ (cpprest, Qt5, Tizen), Clojure, Dart, Elixir, Elm, Eiffel, Erlang, Go, Groovy, Haskell (http-client, Servant), Java (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured), Kotlin, Lua, Node.js (ES5, ES6, AngularJS with Google Closure Compiler annotations) Objective-C, Perl, PHP, PowerShell, Python, R, Ruby, Rust (rust, rust-server), Scala (akka, http4s, swagger-async-httpclient), Swift (2.x, 3.x, 4.x), Typescript (Angular1.x, Angular2.x, Fetch, jQuery, Node).

А также серверные библиотеки для: Ada, C# (ASP.NET Core, NancyFx), C++ (Pistache, Restbed), Erlang, Go, Haskell (Servant), Java (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy, Play Framework, PKMST), Kotlin, PHP (Lumen, Slim, Silex, Symfony, Zend Expressive), Python (Flask), NodeJS, Ruby (Sinatra, Rails5), Rust (rust-server), Scala (Finch, Lagom, Scalatra).

Как генерировать клиентские и серверные библиотеки Swagger?

Достаточно вызвать такую команду:

java -jar swagger-codegen-cli.jar generate --input-spec api.swagger.yml --lang io.swagger.codegen.languages.SymfonyServerCodegen --output app/bundles --template-dir codegen/php-symfony/ --config api.config.swagger.json

Собственно java -jar swagger-codegen-cli.jar generate это запуск бинарного файла с внутренней командой генерации.

—input-spec или сокращённо просто -i это путь или ссылка к swagger-файлу.

—lang или -l это выбор необходимого языка, можно указать как полный неймспейс класса-кодогенератора, например, io.swagger.codegen.languages.SymfonyServerCodegen, так и его алиас, например, php-symfony.

—output или -o это директория в которой будет создана новая директория с библиотекой

—template-dir или -t поможет переопределить путь к папке mustache-шаблонов выбранного генератора. Если не указать, то будет использован тот, что описан в классе в свойствах embeddedTemplateDir и templateDir.

—config или -c указывает на дополнительный файл с конфигурацией кодогенератора.

Конфигурация кодогенератора на примере SymfonyServerCodegen

{
  "packagePath": "SwaggerServerBundle",
  "variableNamingConvention": "snake_case"
}

Это содержимое файла api.config.swagger.json, которое можно указать через опцию —config. С помощью свойства packagePath можно переопределить как будет названа директория с генерируемым кодом. В данном случае библиотека окажется в app/bundles/SwaggerServerBundle/, где app/bundles значение опции —output.

С помощью параметра variableNamingConvention можно переопределить стиль именования имён переменных для параметров API. По-умолчанию, в SymfonyServerCodegen variableNamingConvention = «camelCase». Однако, запросы к апи вида endpoint?antonerVariableName=test выглядят не очень, поэтому с помощью snake_case они становятся endpoint?antoner_variable_name=test.

Создание собственных кодогенераторов

Но как быть, если в списке отсутствует нужный язык или фреймворк? Либо же текущая реализация содержит ошибки, либо в ней не хватает каких-либо функций? Для начала можно ознакомиться с тем, как устроены уже имеющиеся кодогенераторы.

Как устроены генераторы кода в Swagger?

Исходные файлы для генерации библиотек хранятся в двух местах:

swagger-codegen/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/

Здесь находятся классы для предварительной подготовки данных из swagger-файла. Например, для генерации серверной библиотеки PHP-фреймворка Symfony это будет класс SymfonyServerCodegen.java

swagger-codegen/modules/swagger-codegen/src/main/resources/

А здесь находятся mustache-шаблоны для классов и интерфейсов конкретного языка. Для Symfony Server нужно смотреть папку php-symfony. В классе SymfonyServerCodegen.java это объявлено в свойствах:

embeddedTemplateDir = templateDir = "php-symfony";
А в методе указан алиас, по которому можно вызвать данный генератор:
public String getName() {
    return "php-symfony";
}

Как переопределить mustache-шаблоны в Swagger Codegen?

Самый простой способ повлиять на то, что получается на выходе кодогенератора — изменить его шаблоны. Делается очень просто, достаточно скопировать из репозитория директорию с шаблонами для нужного языка и внести в них необходимые изменения. Шаблонизатор Mustache достаточно прост в понимании, но содержит только примитивные инструкции. После чего нужно запустить swagger-codegen-cli.jar с опцией —template-dir my-template-directory/

Как создать свой собственный кодогенератор для Swagger?

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

java -jar swagger-codegen-cli.jar meta -o codegen/evil-generator -n evil-codegen -p ru.evilinside.evilcodegen

После чего в директории codegen/evil-generator окажутся все необходимые файлы для создания собственного генератора для Swagger Codegen. Подробности можно почитать в файле codegen/evil-generator/README.md

Можно сразу же приступить к сборке проекта с помощью Maven и начать использовать свой собственный генератор, для этого нужно перейти в директорию и выполнить:

mvn -X package

Обычно это занимает в пределах 10-30 секунд. И в директории codegen/evil-generator/target окажутся два файла:

  • evil-codegen-swagger-codegen-1.0.0.jar
  • evil-codegen-swagger-codegen-1.0.0-tests.jar

Собственно кодогенератор и сами тесты.

Запускать это дело так:

java -cp swagger-codegen-cli.jar:codegen\evil-generator\target\evil-codegen-swagger-codegen-1.0.0.jar io.swagger.codegen.SwaggerCodegen generate --input-spec api.swagger.yml -l evil-codegen --output app/bundles --config api.config.swagger.json

Для Windows вместо «:» нужно исопользовать «;»:

swagger-codegen-cli.jar;codegen\evil-generator\target\evil-codegen-swagger-codegen-1.0.0.jar

Теперь можно отредактировать код кодогенератора и запускать повторную сборку. Java-класс можно найти тут: codegen/evil-generator/src/main/java/ru/evilinside/evilcodegen/EvilCodegenGenerator.java, а mustache-шаблоны тут: codegen/evil-generator/src/main/resources/evil-codegen.