diff --git a/jsonschema-examples/src/main/java/com/github/victools/jsonschema/examples/NamingStrategyExample.java b/jsonschema-examples/src/main/java/com/github/victools/jsonschema/examples/NamingStrategyExample.java new file mode 100644 index 00000000..c1ddfadc --- /dev/null +++ b/jsonschema-examples/src/main/java/com/github/victools/jsonschema/examples/NamingStrategyExample.java @@ -0,0 +1,117 @@ +/* + * Copyright 2024 VicTools. + * + * 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 + * + * http://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 com.github.victools.jsonschema.examples; + +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.github.victools.jsonschema.generator.Option; +import com.github.victools.jsonschema.generator.OptionPreset; +import com.github.victools.jsonschema.generator.SchemaGenerationContext; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.generator.SchemaVersion; +import com.github.victools.jsonschema.generator.impl.DefinitionKey; +import com.github.victools.jsonschema.generator.naming.SchemaDefinitionNamingStrategy; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Example created in response to #458. + *
+ * Demonstrating usage of the {@code SchemaDefinitionNamingStrategy} feature. + */ +public class NamingStrategyExample implements SchemaGenerationExampleInterface { + + @Override + public ObjectNode generateSchema() { + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON); + configBuilder.with(Option.DEFINITIONS_FOR_ALL_OBJECTS); + configBuilder.forTypesInGeneral() + .withDefinitionNamingStrategy(new SuffixRemovalNamingStrategy("Model")); + SchemaGeneratorConfig config = configBuilder.build(); + SchemaGenerator generator = new SchemaGenerator(config); + return generator.generateSchema(Example.class); + } + + static class SuffixRemovalNamingStrategy implements SchemaDefinitionNamingStrategy { + + private final String typeSuffixToIgnore; + + SuffixRemovalNamingStrategy(String typeSuffixToIgnore) { + this.typeSuffixToIgnore = typeSuffixToIgnore; + } + + @Override + public String getDefinitionNameForKey(DefinitionKey key, SchemaGenerationContext generationContext) { + return this.getDefinitionNameForType(key.getType()); + } + + private String getDefinitionNameForType(ResolvedType type) { + Class erasedType = type.getErasedType(); + String definitionName = erasedType.getSimpleName(); + if (definitionName.endsWith(this.typeSuffixToIgnore) && definitionName.length() > this.typeSuffixToIgnore.length()) { + definitionName = definitionName.substring(0, definitionName.length() - this.typeSuffixToIgnore.length()); + } + List typeParameters = type.getTypeParameters(); + if (!typeParameters.isEmpty()) { + definitionName += typeParameters.stream() + .map(this::getDefinitionNameForType) + .collect(Collectors.joining(", ", "<", ">")); + } + return definitionName; + } + + @Override + public void adjustDuplicateNames(Map subschemasWithDuplicateNames, SchemaGenerationContext generationContext) { + char index = 'A'; + for (Map.Entry singleEntry : subschemasWithDuplicateNames.entrySet()) { + singleEntry.setValue(singleEntry.getValue() + "-" + index); + index++; + } + } + } + + static class Example { + public List> fooArray; + public Bar barWithoutRenaming; + public BarModel barModelDuplicate; + public Model modelWithoutRenaming; + public FooBarModel fooBarGeneric; + } + + static class FooModel { + public T nested; + } + + static class Bar { + public int value; + } + + static class BarModel { + public String value; + } + + static class FooBarModel { + public T nested; + } + + static class Model { + public String value; + } +} diff --git a/jsonschema-examples/src/test/java/com/github/victools/jsonschema/examples/ExampleTest.java b/jsonschema-examples/src/test/java/com/github/victools/jsonschema/examples/ExampleTest.java index 98d4308a..594653c1 100644 --- a/jsonschema-examples/src/test/java/com/github/victools/jsonschema/examples/ExampleTest.java +++ b/jsonschema-examples/src/test/java/com/github/victools/jsonschema/examples/ExampleTest.java @@ -40,6 +40,7 @@ public class ExampleTest { InheritanceRefExample.class, JacksonDescriptionAsTitleExample.class, JacksonSubtypeDefinitionExample.class, + NamingStrategyExample.class, SingleArrayItemExample.class, StrictTypeInfoExample.class, SubtypeLookUpExample.class, diff --git a/jsonschema-examples/src/test/resources/com/github/victools/jsonschema/examples/NamingStrategyExample-result.json b/jsonschema-examples/src/test/resources/com/github/victools/jsonschema/examples/NamingStrategyExample-result.json new file mode 100644 index 00000000..7eaf66fc --- /dev/null +++ b/jsonschema-examples/src/test/resources/com/github/victools/jsonschema/examples/NamingStrategyExample-result.json @@ -0,0 +1,66 @@ +{ + "$schema" : "https://json-schema.org/draft/2020-12/schema", + "$defs" : { + "Bar-A" : { + "type" : "object", + "properties" : { + "value" : { + "type" : "string" + } + } + }, + "Bar-B" : { + "type" : "object", + "properties" : { + "value" : { + "type" : "integer" + } + } + }, + "Foo(Model)" : { + "type" : "object", + "properties" : { + "nested" : { + "$ref" : "#/$defs/Model" + } + } + }, + "FooBar(Bar)" : { + "type" : "object", + "properties" : { + "nested" : { + "$ref" : "#/$defs/Bar-A" + } + } + }, + "Model" : { + "type" : "object", + "properties" : { + "value" : { + "type" : "string" + } + } + } + }, + "type" : "object", + "properties" : { + "barModelDuplicate" : { + "$ref" : "#/$defs/Bar-A" + }, + "barWithoutRenaming" : { + "$ref" : "#/$defs/Bar-B" + }, + "fooArray" : { + "type" : "array", + "items" : { + "$ref" : "#/$defs/Foo(Model)" + } + }, + "fooBarGeneric" : { + "$ref" : "#/$defs/FooBar(Bar)" + }, + "modelWithoutRenaming" : { + "$ref" : "#/$defs/Model" + } + } +} \ No newline at end of file