Pull to refresh

Comments 4

Пользуясь случаем, хочу спросить: есть ли рабочий генератор, который из json-схемы сможет сгенерировать файлик для swagger? По сути для документирования API и для валидации его ответа приходится писать практически дублирующийся код, что часто не очень удобно.
Я не знаком со swagger, но, пролистав документацию swagger.io/specification, создается впечатление, что он и так использует json schema v4 (с небольшими расширениями). Подозреваю, ваш случай решается страницей кода на питоне. Хотя, опять же, с темой не знаком.
Да, но так хочется писать код, а не тулзы для него :)
Хорошую тему вы подняли! В целом работа с JSON в C++ сродни кошмару. Самое удобное, что я нашел для себя, это Mongo BSON C++ 11 драйвер (несмотря на то, что он про BSON, c JSON работает идеально), который дает вот такой интерфейс для разбора JSON, github.com/mongodb/mongo-cxx-driver/blob/master/examples/bsoncxx/getting_values.cpp и вот такой для его генерации — github.com/mongodb/mongo-cxx-driver/blob/master/examples/bsoncxx/builder_basic.cpp

На мой взгляд из того, что я видел — это наиболее удобный и «родной» подход для С++ 11. Но задачу автоматической сериализации класса в JSON и де-сериализации оно не решает.

В итоге делаю не особо хорошо, есть yaml описание, в котором со своей структурой типов а-ля protobuf описана структура данных.

Из нее генерируется описание класса и сериализатор/десериализатор на базе Mongo BSON CXX 11. Все это дело написано на Perl (в целом-то без разницы на чем его делать, логика довольно простая) и на выходе получаются огромные полотна по несколько тысяч строк вызовов bson структур с проверкой. Внутри скрипта генератора также реализован маппинг между типами Mongo BSON CXX (k_utf8) и типами С++ (std::string и прочие соотвественно).

Например, чтение целочисленного поля выглядит вот так (тут еще добавлен опциональный валидатор на основе данных, которые используются в моем случае, он тоже автоматически генерируется):
    // Process option snmp_oid   
    auto config_snmp_oid = doc_view["snmp_oid"];

    if (config_snmp_oid.type() != bsoncxx::type::k_utf8) {
        logger << log4cpp::Priority::ERROR << "Could not read key snmp_oid from MongoDB because it has incorrect type";
        return false;
    }

    uplink_configuration.snmp_oid = config_snmp_oid.get_utf8().value.to_string();
    if (!validate_string(uplink_configuration.snmp_oid)) {
        logger << log4cpp::Priority::ERROR << "Validation of variable snmp_oid failed, please check it format.";
        return false;
    }


Я бы не сказал, что данный подход мне нравится. В идеале хотелось бы что-то в стиле Go, когда прямо напротив переменной-класса описывается ее JSON имя и обозначается необходимости сериализации и сериализатор/десериализатор генерируется автоматически.

Но увы без макро-процессора такое не сделать…
Sign up to leave a comment.

Articles