Импорт XSD в OpenAPI - PullRequest
       12

Импорт XSD в OpenAPI

2 голосов
/ 07 мая 2019

У меня есть некоторое определение модели в файле XSD, и мне нужно сослаться на эти модели из определения OpenApi.Модификация вручную невозможна, поскольку файл слишком велик, и мне нужно поместить его в систему сборки, чтобы при изменении XSD я мог заново создать модели / схемы для OpenApi.

Что я пробовали то, что почти сработало, использует xsd2json и затем конвертирует его с помощью модуля узла json-schema-to-openapi .Однако xsd2json отказывается от некоторых моделей complexElement.Например, "$ref": "#/definitions/tns:ContentNode" используется внутри одной модели как дочерний тип, но в схеме нет определения для ContentNode, где, когда я смотрю в XSD, есть определение complexElement для ContentNode.

Другой подход, который я еще не пробовал, но мне кажется немного чрезмерным, - это использование xjb для генерации моделей Java из XSD, а затем использование JacksonSchema для генерации схемы json.

Есть ли какие-либо установленныебиблиотека или способ использования XSD в OpenApi?

Ответы [ 2 ]

1 голос
/ 07 мая 2019

В итоге я реализовал второй подход, используя jaxb для преобразования XSD в java-модели, а затем использовал Джексона для записи схем в файлы.

Gradle:

plugins {
    id 'java'
    id 'application'
}

group 'foo'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-jsonSchema', version: '2.9.8'
}

configurations {
    jaxb
}

dependencies {
    jaxb (
            'com.sun.xml.bind:jaxb-xjc:2.2.7',
            'com.sun.xml.bind:jaxb-impl:2.2.7'
    )
}

application {
    mainClassName = 'foo.bar.Main'
}

task runConverter(type: JavaExec, group: 'application') {
    classpath = sourceSets.main.runtimeClasspath

    main = 'foo.bar.Main'
}

task jaxb {
    System.setProperty('javax.xml.accessExternalSchema', 'all')
    def jaxbTargetDir = file("src/main/java")

    doLast {
        jaxbTargetDir.mkdirs()

        ant.taskdef(
                name: 'xjc',
                classname: 'com.sun.tools.xjc.XJCTask',
                classpath: configurations.jaxb.asPath
        )
        ant.jaxbTargetDir = jaxbTargetDir

        ant.xjc(
                destdir: '${jaxbTargetDir}',
                package: 'foo.bar.model',
                schema: 'src/main/resources/crs.xsd'
        )
    }
}

compileJava.dependsOn jaxb

С конвертеромОсновной класс, который делает что-то вроде:

package foo.bar;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;
import foo.bar.model.Documents;

public class Main {

    public static void main(String[] args) {
        ObjectMapper mapper = new ObjectMapper();
        JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper);
        try {
            JsonSchema schema = schemaGen.generateSchema(Documents.class);
            System.out.print(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

}

Это все еще не идеально, хотя ... это должно было бы перебрать все классы модели и сгенерировать файл со схемой.Также он не использует ссылки, если у класса есть член другого класса, схема печатается внутри строки вместо ссылки.Это требует немного больше настроек с SchemaFactoryWrapper, но может быть сделано.

0 голосов
/ 07 мая 2019

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

Исходя из предложенного вами альтернативного подхода, я бы предложил аналогичное решение:

OpenAPI, очевидно, является стандартом определения API. Для вас должна быть возможность использовать подход, основанный на коде, сочиняя операции API в коде и раскрывая типы, сгенерированные из XJB. Затем вы можете использовать Apiee и его аннотации для генерации определения OpenAPI. Это предполагает, что вы используете JAX-RS для своего API.

Это все еще двухэтапный процесс, но с более высоким шансом на успех. Преимущество здесь в том, что ваш первый шаг, вывод из ваших XSD-типов в java-типы, будем надеяться, будет иметь очень небольшое влияние (если таковое имеется) на код, который определяет ваши операции API. Несмотря на то, что все еще будет ручной шаг (обновление моделей), определение OpenAPI будет обновляться автоматически после перестройки кода.

...