Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Import XSD to OpenAPI

Tags:

json

xsd

openapi

I have some model definition inside a XSD file and I need to reference these models from an OpenApi definition. Manually remodeling is no option since the file is too large, and I need to put it into a build system, so that if the XSD is changed, I can regenerate the models/schemas for OpenApi.

What I tried and what nearly worked is using xsd2json and then converting it with the node module json-schema-to-openapi. However xsd2json is dropping some of the complexElement models. For example "$ref": "#/definitions/tns:ContentNode" is used inside of one model as the child type but there is no definition for ContentNode in the schema, where when I look into the XSD, there is a complexElement definition for ContentNode.

Another approach which I haven't tried yet but seems a bit excessive to me is using xjb to generate Java models from the XSD and then using JacksonSchema to generate the json schema.

Is there any established library or way, to use XSD in OpenApi?

like image 808
Tom Avatar asked May 07 '19 08:05

Tom


People also ask

Does OpenAPI support XML?

The OpenAPI 3 format offers a special xml object to help you fine-tune representation of XML data. You can use this object to transform some properties to attributes rather than elements, to change element names, to add namespaces and to control transformations of array items.

How do you convert XSD to JSON schema?

Plugin for converting an XML Schema (XSD) file to a JSON Schema file. Once installed, go to Tools -> XML Actions, or right-click on an XML Schema file from Project view, and select "Convert XSD to JSON Schema".

Is OpenAPI a JSON schema?

OpenAPI 3.0 data types are based on an extended subset JSON Schema Specification Wright Draft 00 (aka Draft 5). The data types are described using a Schema object.

Is YAML OpenAPI?

OpenAPI allows for either a JSON or YAML format. We recommend using the YAML format, and use it in our examples.


1 Answers

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.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

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.

like image 79
Tom Avatar answered Oct 19 '22 18:10

Tom