annotationProcessor("io.micronaut.jsonschema:micronaut-json-schema-processor")
Micronaut JSON schema
JSON schema support for Micronaut
Version: 1.2.0
1 Introduction
JSON Schema is a human-readable format for exchanging data that also enables JSON data consistency, validity and interoperability.
Micronaut JSON Schema allows creating schemas for beans in your applications.
2 Dependencies
To get started add Micronaut JSON Schema processor to the annotation processor scope of your build configuration:
<annotationProcessorPaths>
<path>
<groupId>io.micronaut.jsonschema</groupId>
<artifactId>micronaut-json-schema-processor</artifactId>
</path>
</annotationProcessorPaths>
and the Micronaut JSON Schema Annotations dependency to compile classpath
implementation("io.micronaut.jsonschema:micronaut-json-schema-annotations")
<dependency>
<groupId>io.micronaut.jsonschema</groupId>
<artifactId>micronaut-json-schema-annotations</artifactId>
</dependency>
3 Quick Start
Annotate a bean with JsonSchema to trigger the creation of a schema for it during build time:
package io.micronaut.jsonschema.test;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import io.micronaut.jsonschema.JsonSchema;
import io.micronaut.serde.annotation.Serdeable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.PositiveOrZero;
/**
* A llama. (4)
*
* @param name The name
* @param age The age
*/
@JsonSchema // (1)
@Serdeable // (2)
public record Llama(
@NotBlank // (3)
@JsonInclude(Include.NON_NULL)
String name,
@PositiveOrZero // (3)
Integer age
) {
}
package io.micronaut.jsonschema.test
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonInclude.Include
import io.micronaut.jsonschema.JsonSchema
import io.micronaut.serde.annotation.Serdeable
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.PositiveOrZero
/**
* A llama. (4)
*/
@JsonSchema // (1)
@Serdeable // (2)
class Llama {
/**
* The name.
*/
@NotBlank // (3)
@JsonInclude(Include.NON_NULL)
String name
/**
* The age.
*/
@PositiveOrZero // (3)
Integer age
}
package io.micronaut.jsonschema.test
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonInclude.Include
import io.micronaut.jsonschema.JsonSchema
import io.micronaut.serde.annotation.Serdeable
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.PositiveOrZero
/**
* A llama. (4)
*
* @param name The name
* @param age The age
*/
@JsonSchema // (1)
@Serdeable // (2)
class Llama(
@field:JsonInclude(Include.NON_NULL)
@field:NotBlank
val name: String,
@field:PositiveOrZero
val age: Int? // (3)
)
1 | Add the JsonSchema annotation. |
2 | (Optional) To use Micronaut Serialization as the serialization solution for your application refer to the
Micronaut Serialization
documentation and add Serdeable annotation to the bean. |
3 | Add additional required annotations to your bean. See supported annotations in the following sections. |
4 | The JavaDoc will be added as schema description. |
The following file will be created on the classpath: META-INF/schemas/llama.schema.json
.
{
"$schema":"https://json-schema.org/draft/2020-12/schema",
"$id":"http://localhost:8080/schemas/llama.schema.json",
"title":"Llama",
"description":"A llama. <4>",
"type":["object"],
"properties":{
"age":{
"description":"The age",
"type":["integer"],
"minimum":0
},
"name":{
"description":"The name",
"type":["string"],
"minLength":1
}
},
"required":["age"]
}
It can be used in your application and will be included in the jar file.
4 JSON Schema Configuration
The generation can be configured globally with annotation processor options:
// For Java
tasks.withType(JavaCompile).configureEach {
options.compilerArgs.add("-Amicronaut.jsonschema.baseUri=https://example.com/schemas") // (1)
}
// For Groovy
tasks.withType(GroovyCompile).configureEach {
options.compilerArgs.add("-Amicronaut.jsonschema.baseUri=https://example.com/schemas") // (1)
}
// For KSP
ksp {
arg("micronaut.jsonschema.baseUri", "https://example.com/schemas") // (1)
}
// For Kapt
kapt {
arguments {
arg("micronaut.jsonschema.baseUri", "https://example.com/schemas") // (1)
}
}
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-Amicronaut.jsonschema.baseUri=https://example.com/schemas</arg> <!-- (1) -->
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
1 | Set the base URL for all the schemas. It will be prepended to all relative schema URLs. |
With the previous configuration, the following file will be created on the classpath: META-INF/schemas/llama.schema.json
.
{
"$schema":"https://json-schema.org/draft/2020-12/schema",
"$id":"https://example.com/schemas/llama.schema.json",
"title":"Llama",
"description":"A llama. <4>",
"type":["object"],
"properties":{
"age":{
"description":"The age",
"type":["integer"],
"minimum":0
},
"name":{
"description":"The name",
"type":["string"],
"minLength":1
}
}
}
All the supported options are:
Option | Description |
---|---|
|
Set the base URL for all the schemas. It will be prepended to all relative schema URLs. |
|
The location where JSON schemas will be generated inside the build |
|
Whether to encode byte array as a JSON array. The default and preferred behavior is to encode it as a Base64-encoded string. |
|
Specify the JSON Schema draft versions. Currently only |
|
Whether to generate schemas in strict mode. In strict mode unresolved properties in JSON will cause an error. All the properties that are not annotated as nullable must be non-null. |
5 JSON Schema Annotation Members
Schema generation can be configured with properties of the JsonSchema annotation, for example:
@JsonSchema(
title = "RedWingedBlackbird", // (1)
description = "A species of blackbird with red wings",
uri = "/red-winged-blackbird" // (2)
)
@Serdeable
public record RWBlackbird(
String name,
Double wingSpan
) {
}
@JsonSchema(
title = "RedWingedBlackbird", // (1)
description = "A species of blackbird with red wings",
uri = "/red-winged-blackbird" // (2)
)
@Serdeable
class RWBlackbird {
/**
* The name.
*/
String name
/**
* The wingspan.
*/
Double wingSpan
}
@JsonSchema(
title = "RedWingedBlackbird", // (1)
description = "A species of blackbird with red wings",
uri = "/red-winged-blackbird" // (2)
)
@Serdeable
class RWBlackbird (
val name: String,
val wingSpan: Double?
)
1 | Configure the title and description of the generated JSON Schema. |
2 | Set the relative or absolute URL. This will affect the file name as well as the id by which this schema can be referenced. |
For the previous class, the following file will be created on the classpath: META-INF/schemas/red-winged-blackbird.schema.json
.
{
"$schema":"https://json-schema.org/draft/2020-12/schema",
"$id":"http://localhost:8080/schemas/red-winged-blackbird.schema.json",
"title":"RedWingedBlackbird",
"description":"A species of blackbird with red wings",
"type":["object"],
"properties":{
"name":{
"description":"The name",
"type":["string"]
},
"wingSpan":{
"description":"The wing span of the bird",
"type":["number"]
}
}
}
6 Serving JSON Schemas
To expose the generated JSON Schema output from your running application, add static resources configuration.
micronaut.router.static-resources.jsonschema.paths=classpath:META-INF/schemas
micronaut.router.static-resources.jsonschema.mapping=/schemas/**
micronaut.jsonschema.validation.baseUri=https://example.com/schemas
1 | The schemas are exposed on the /schemas path, which can be customized for your specific needs. |
2 | The schemas are be read from the META-INF/schemas classpath folder. |
7 JSON Schema Validation
If you want to validate a JSON file against your generated JSON Schema, you can inject a bean of type JsonSchemaValidator. You need the following dependency:
implementation("io.micronaut.jsonschema:micronaut-json-schema-validation")
<dependency>
<groupId>io.micronaut.jsonschema</groupId>
<artifactId>micronaut-json-schema-validation</artifactId>
</dependency>
8 Supported Information Sources
Information for JSON schema is aggregated from multiple sources.
8.1 JavaDoc
JavaDoc on types and properties will be added to the description properties of schemas. This includes class, property descriptions and record parameter descriptions.
8.2 Validation Annotations
The following jakarta.validation.constraints
annotations are supported:
Validation Annotations | Supported | Comment |
---|---|---|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
❌ |
JSON schema does not define fields for validating date-time formats |
|
❌ |
JSON schema does not define fields for validating date-time formats |
|
❌ |
JSON schema does not define fields for validating date-time formats |
|
❌ |
JSON schema does not define fields for validating date-time formats |
By default, properties are not nullable. jakarta.annotations.Nullable
can be added to make them nullable.
Note, that validation might not correspond to actual bean values, as by default null
values are completely omitted during JSON serialization.
Custom validators cannot be supported, as this information is implementation-specific and not available during build time. |
8.3 Jackson Annotations
The following com.fasterxml.jackson.annotation
annotations are supported:
Jackson Annotations | Supported | Comment |
---|---|---|
|
✅ |
The annotation has no effect |
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
The annotation has no effect |
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
✅ |
The annotation has no effect |
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
Cannot be supported* |
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
|
|
❌ |
*Custom serializers and deserializers cannot be supported, as this information is implementation-specific
and not available during build time. This also applies to some other features, like the JsonFilter annotation
which allows defining custom filters.
|
9 Repository
You can find the source code of this project in this repository:
10 Release History
For this project, you can find a list of releases (with release notes) here: