Import XSD to OpenAPI Import XSD to OpenAPI json json

Import XSD to OpenAPI


I ended up implementing the second approach using jaxb to convert the XSD to java models and then using Jackson to write the schemas to files.

Gradle:

plugins {    id 'java'    id 'application'}group 'foo'version '1.0-SNAPSHOT'sourceCompatibility = 1.8repositories {    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

With a converter main class, that does something along the lines of:

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();        }    }}

It is still not perfect though,... this would need to iterate over all the model classes and generate a file with the schema. Also it doesn't use references, if a class has a member of another class, the schema is printed inline instead of referencing. This requires a bit more customization with the SchemaFactoryWrapper but can be done.


The problem you have is that you are applying inference tooling over a multi-step conversion. As you have found, inference tooling is inherently fussy and will not work in all situations. It's kind of like playing Chinese whispers - every step of the chain is potentially lossy, so what you get out the other end may be garbled.

Based on the alternative approach you suggest, I would suggest a similar solution:

OpenAPI is, rather obviously, an API definition standard. It should be possible for you to take a code first approach, composing your API operations in code and exposing the types generated from XJB. Then you can use Apiee and its annotations to generate the OpenAPI definition. This assumes you are using JAX-RS for your API.

This is still a two-step process, but one with a higher chance of success. The benefit here is that your first step, inferring your XSD types into java types, will hopefully have very little (if any) impact on the code which defines your API operations. Although there will still be a manual step (updating the models) the OpenAPI definition will update automatically once the code has been rebuilt.