Skip to content

Commit

Permalink
Create an initial version of the JSON schema processors
Browse files Browse the repository at this point in the history
  • Loading branch information
andriy-dmytruk committed Apr 3, 2024
1 parent d438db9 commit 2008eb5
Show file tree
Hide file tree
Showing 62 changed files with 3,331 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
id 'io.micronaut.build.internal.json-schema-base'
id "io.micronaut.build.internal.module"
}

micronautBuild {
binaryCompatibility {
enabled.set(false)
}
}

This file was deleted.

3 changes: 3 additions & 0 deletions config/checkstyle/suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@
<!-- files="DefaultBeanContext.java|BeanDefinitionWriter.java|DefaultHttpClient.java"/> -->

<suppress checks="MissingJavadocType" files=".*doc-examples.*" />
<suppress checks="MethodName" files=".*jsonschema.visitor.model.Schema.java" />
<suppress checks="ParameterName" files=".*jsonschema.visitor.model.Schema.java" />

</suppressions>
10 changes: 5 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
projectVersion=1.0.0-SNAPSHOT
projectGroup=io.micronaut.project-template
projectGroup=io.micronaut.jsonschema

title=Micronaut project-template
projectDesc=TODO
title=Micronaut JSON schema
projectDesc=JSON schema support for Micronaut
projectUrl=https://micronaut.io
githubSlug=micronaut-projects/micronaut-project-template
developers=Graeme Rocher
githubSlug=micronaut-projects/micronaut-json-schema
developers=Andriy Dmytruk
org.gradle.caching=true
org.gradle.jvmargs=-Xmx1g
33 changes: 15 additions & 18 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,30 @@
[versions]
micronaut = "4.3.12"
micronaut-docs = "2.0.0"
micronaut-logging = "1.2.0"
micronaut-serde = "2.5.1"
micronaut-test = "4.2.1"
micronaut-validation = "4.2.0"

groovy = "4.0.17"
json-schema-validator = "1.4.0"
kotlin = "1.9.23"
ksp = "1.9.23-1.0.19"
spock = "2.3-groovy-4.0"

# Managed versions appear in the BOM
# managed-somelib = "1.0"
# managed-somebom = "1.1"

[libraries]
# Core
micronaut-core = { module = 'io.micronaut:micronaut-core-bom', version.ref = 'micronaut' }
micronaut-logging = { module = "io.micronaut.logging:micronaut-logging-bom", version.ref = "micronaut-logging" }
micronaut-serde = { module = "io.micronaut.serde:micronaut-serde-bom", version.ref = "micronaut-serde" }
micronaut-test = { module = "io.micronaut.test:micronaut-test-bom", version.ref = "micronaut-test" }
micronaut-validation = { module = "io.micronaut.validation:micronaut-validation-bom", version.ref = "micronaut-validation" }

#
# Managed dependencies appear in the BOM
#
# managed-somelib = { module = "group:artifact", version.ref = "managed-somelib" }

#
# Imported BOMs, also appearing in the generated BOM
#
# boms-somebom = { module = "com.foo:somebom", version.ref = "managed-somebom" }

# Other libraries used by the project but non managed
json-schema-validator = { module = "com.networknt:json-schema-validator", version.ref = "json-schema-validator" }

# micronaut-bom = { module = "io.micronaut:micronaut-bom", version.ref = "micronaut" }
# jdoctor = { module = "me.champeau.jdoctor:jdoctor-core", version.ref="jdoctor" }

[bundles]

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
17 changes: 17 additions & 0 deletions json-schema-annotations/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
plugins {
id 'io.micronaut.build.internal.json-schema-module'
}

dependencies {

}

configurations.configureEach {
all*.exclude group: "ch.qos.logback"
}

test {
useJUnitPlatform()

maxHeapSize = "1024m"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.jsonschema;

/**
* An annotation that signifies that json schema should be created for the object.
* The JSON schema will attempt to mimic the way this object would be serialized.
*
* @since 1.0.0
* @author Andriy Dmytruk
*/
public @interface JsonSchema {

/**
* The title of the JSON schema.
* By default, the class name will be used.
*
* @return The title
*/
String title() default "";

/**
* The description of the JSON schema.
* By default, javadoc of the object will be used.
*
* @return The description
*/
String description() default "";

/**
* The schema's relative or absolute URI.
* The default will create the URI based on class name and configured base URI.
*
* @return The URI
*/
String uri() default "";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.jsonschema;

/**
* An annotation for globally configuring the JSON schema generation.
*
* @since 1.0.0
* @author Andriy Dmytruk
*/
public @interface JsonSchemaConfiguration {

/**
* The location where JSON schemas will be generated inside the build {@code META-INF/} directory.
*
* @return The output location
*/
String outputLocation() default "schemas";

/**
* The base URI to be used for schemas.
*
* @return The base URI
*/
String baseUri();

/**
* Whether to encode byte array as a JSON array.
* The default and preferred behavior is to encode it as a Base64 string.
*
* @return Whether to represent binary data as array
*/
boolean binaryAsArray() default false;

}
11 changes: 11 additions & 0 deletions json-schema-bom/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
id 'io.micronaut.build.internal.json-schema-base'
id "io.micronaut.build.internal.bom"
}

micronautBuild {
binaryCompatibility {
enabled.set(false)
}
}

31 changes: 31 additions & 0 deletions json-schema-processor/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
plugins {
id 'io.micronaut.build.internal.json-schema-module'
}

dependencies {
compileOnly(mn.micronaut.core.processor)

implementation(mn.micronaut.http)

api(projects.micronautJsonSchemaAnnotations)
api(mn.jackson.databind)

testImplementation(mnValidation.validation)
testImplementation(mn.micronaut.inject.kotlin.test)
testImplementation(mn.micronaut.inject.groovy.test)
testImplementation(mn.micronaut.inject.java.test)
testImplementation(mnLogging.logback.classic)
testImplementation(mnLogging.logback.core)
testImplementation(mnLogging.slf4j.api)
testImplementation(mnLogging.slf4j.simple)
}

configurations.configureEach {
all*.exclude group: "ch.qos.logback"
}

test {
useJUnitPlatform()

maxHeapSize = "1024m"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.jsonschema.visitor;

import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.core.annotation.Internal;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.inject.ast.ClassElement;
import io.micronaut.inject.visitor.TypeElementVisitor;
import io.micronaut.inject.visitor.VisitorContext;
import io.micronaut.jsonschema.JsonSchemaConfiguration;
import io.micronaut.jsonschema.visitor.model.Schema;

import java.util.HashMap;
import java.util.Map;

/**
* A visitor for reading the JSON schema configuration.
* It must be defined with a {@link JsonSchemaConfiguration} annotation on a bean.
*
* @since 1.0.0
* @author Andriy Dmytruk
*/
@Internal
public final class JsonSchemaConfigurationVisitor implements TypeElementVisitor<JsonSchemaConfiguration, Object> {

public static final String JSON_SCHEMA_CONFIGURATION_PROPERTY = "io.micronaut.jsonschema.config";

@Override
public int getOrder() {
return 1; // Run before the JSON Schema visitor
}

@Override
public @NonNull TypeElementVisitor.VisitorKind getVisitorKind() {
return VisitorKind.AGGREGATING;
}

@Override
public void visitClass(ClassElement element, VisitorContext visitorContext) {
AnnotationValue<?> annotation = element.getAnnotation(JsonSchemaConfiguration.class);
if (annotation != null) {
String outputLocation = annotation.stringValue("outputLocation")
.orElse(JsonSchemaContext.DEFAULT_OUTPUT_LOCATION);
String baseUri = annotation.getRequiredValue("baseUri", String.class);
if (baseUri.endsWith("/")) {
baseUri = baseUri.substring(0, baseUri.length() - 1);
}
boolean binaryAsArray = annotation.booleanValue("binaryAsArray")
.orElse(JsonSchemaContext.DEFAULT_BINARY_AS_ARRAY);
JsonSchemaContext context = new JsonSchemaContext(outputLocation, baseUri, binaryAsArray, new HashMap<>());
visitorContext.put(JSON_SCHEMA_CONFIGURATION_PROPERTY, context);
}
}

/**
* A configuration for the JSON schema.
*
* @param outputLocation The output location for schemas
* @param baseUrl The base URL of the schemas
* @param binaryAsArray Whether to represent byte arrays as arrays instead of base 64 string
* @param createdSchemasByType A cache of crated schemas
*/
public record JsonSchemaContext(
String outputLocation,
String baseUrl,
boolean binaryAsArray,
Map<String, Schema> createdSchemasByType
) {
public static final String DEFAULT_OUTPUT_LOCATION = "schemas";
public static final boolean DEFAULT_BINARY_AS_ARRAY = false;

public static JsonSchemaContext createDefault() {
return new JsonSchemaContext(
DEFAULT_OUTPUT_LOCATION, null, DEFAULT_BINARY_AS_ARRAY, new HashMap<>()
);
}
}

}
Loading

0 comments on commit 2008eb5

Please sign in to comment.