Repository: victools/jsonschema-generator
Pull request #285 (2022-09-25 20:22:39)

feat: Enable type definition for members declaring a supertype
Addresses issue #280 and perhaps #283.

#### Cause: "It's not a bug, it's a feature"
When encountering a member (field/method), that declares a supertype, i.e., one that has at least one explicit subtype, the current (default) behavior is to generate the member schema (considering the full field/method context, including annotations etc.) for each subtype as if that member had declared this particular subtype instead.

#### Solution: new `Option.DEFINITIONS_FOR_MEMBER_SUPERTYPES`
When this new `Option` is enabled (which it's not by default), then the subtypes are only considered as generic type, i.e., not in the context of the particular member (field/method). That allows a common definition to be produced, that can be re-used.
The side effect is, that a supertype that would otherwise always be replaced can now get its own entry in the `$defs`/`definitions`.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index afa18f4..67fb790 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased]
+### `jsonschema-generator`
+#### Added
+- new `Option.DEFINITIONS_FOR_MEMBER_SUPERTYPES` to disable the transparent member subtype resolution, i.e., enable inclusion of a supertype schema
+
+#### Changed
+- enable moving subtype schema into `$defs` and thereby reduce number of unnecessary `anyOf` wrappers
+
 ### `jsonschema-maven-plugin`
 #### Added
 - support `<classpath>` parameter in order to also consider compile dependencies for the schema generation (and/or ignoring runtime dependencies)
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/Option.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/Option.java
index 8e45fce..8f17757 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/Option.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/Option.java
@@ -257,6 +257,14 @@ public enum Option {
      * @since 4.11.0
      */
     DEFINITION_FOR_MAIN_SCHEMA(null, null),
+    /**
+     * Whether a member (field/method), having a declared type for which subtypes are being detected, should be included as standalone definition with
+     * any collected member attributes assigned directly – and the subtypes only being handled as generic types – or each of its subtypes should be
+     * treated as alternative sub-schema for this member (field/method) including any attributes derived from that member.
+     *
+     * @since 4.27.0
+     */
+    DEFINITIONS_FOR_MEMBER_SUPERTYPES(null, null),
     /**
      * Whether all sub-schemas should be defined in-line, i.e. including no "definitions"/"$defs". This takes precedence over
      * {@link #DEFINITIONS_FOR_ALL_OBJECTS} and {@link #DEFINITION_FOR_MAIN_SCHEMA}.
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java
index 1fd6313..08cf454 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfig.java
@@ -64,6 +64,17 @@ public interface SchemaGeneratorConfig {
      */
     boolean shouldCreateDefinitionForMainSchema();
 
+    /**
+     * Determine whether a member (field/method), having a declared type for which subtypes are being detected, should be merely a collection of its
+     * subtype schemas – each being treated like the member had declared the subtype directly – or whether it should be included as standalone
+     * definition with any collected member attributes assigned directly and the subtypes only being handled as generic types.
+     *
+     * @return whether to produce sub-schema for each subtype of a member's declared type, like the member had declared that subtype instead
+     *
+     * @since 4.27.0
+     */
+    boolean shouldTransparentlyResolveSubtypesOfMembers();
+
     /**
      * Determine whether all sub-schemas should be included in-line, even if they occur multiple times, and not in the schema's "definitions"/"$defs".
      *
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaCleanUpUtils.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaCleanUpUtils.java
index 060b35d..ac9cb2d 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaCleanUpUtils.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaCleanUpUtils.java
@@ -49,6 +49,9 @@ public class SchemaCleanUpUtils {
 
     /**
      * Remove and merge {@link SchemaKeyword#TAG_ALLOF} parts when there are no conflicts between the sub-schemas.
+     * <br>
+     * This makes for more readable schemas being generated but has the side-effect that manually added {@link SchemaKeyword#TAG_ALLOF} (e.g. from a
+     * custom definition or attribute overrides) may be removed as well if it isn't strictly speaking necessary.
      *
      * @param jsonSchemas generated schemas that may contain unnecessary {@link SchemaKeyword#TAG_ALLOF} nodes
      */
@@ -59,6 +62,9 @@ public class SchemaCleanUpUtils {
 
     /**
      * Reduce nested {@link SchemaKeyword#TAG_ANYOF} parts when one contains an entry with only another {@link SchemaKeyword#TAG_ANYOF} inside.
+     * <br>
+     * This makes for more readable schemas being generated but has the side-effect that manually added {@link SchemaKeyword#TAG_ANYOF} (e.g. from a
+     * custom definition or attribute overrides) may be removed as well if it isn't strictly speaking necessary.
      *
      * @param jsonSchemas generated schemas that may contain unnecessary nested {@link SchemaKeyword#TAG_ANYOF} nodes
      */
@@ -110,10 +116,10 @@ public class SchemaCleanUpUtils {
     }
 
     /**
-     * Iterate through a generated and fully populated schema and remove extraneous {@link SchemaKeyword#TAG_ANYOF} nodes, where one entry of the
-     * array is again a {@link SchemaKeyword#TAG_ANYOF} wrapper and nothing else. This makes for more readable schemas being generated but has the
-     * side-effect that any manually added {@link SchemaKeyword#TAG_ANYOF} (e.g. through a custom definition of attribute overrides) may be removed as
-     * well if it isn't strictly speaking necessary.
+     * Iterate through a generated and fully populated schema and perform the provided clean-up remove extraneous {@link SchemaKeyword#TAG_ANYOF}
+     * nodes, where one entry of the array is again a {@link SchemaKeyword#TAG_ANYOF} wrapper and nothing else. This makes for more readable schemas
+     * being generated but has the side-effect that any manually added {@link SchemaKeyword#TAG_ANYOF} (e.g. through a custom definition of attribute
+     * overrides) may be removed as well if it isn't strictly speaking necessary.
      *
      * @param schemaNodes generated schemas to clean-up
      * @param performCleanUpOnSingleSchemaNode clean up task to execute before looking for deeper nested sub-schemas for which to apply the same
@@ -176,26 +182,26 @@ public class SchemaCleanUpUtils {
                 .filter(part -> part instanceof ObjectNode)
                 .map(part -> (ObjectNode) part)
                 .collect(Collectors.toList());
-
         // collect all defined attributes from the separate parts and check whether there are incompatible differences
         Map<String, List<JsonNode>> fieldsFromAllParts = Stream.concat(Stream.of(schemaNode), parts.stream())
                 .flatMap(part -> StreamSupport.stream(((Iterable<Map.Entry<String, JsonNode>>) () -> part.fields()).spliterator(), false))
                 .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
         if ((this.config.getSchemaVersion() == SchemaVersion.DRAFT_6 || this.config.getSchemaVersion() == SchemaVersion.DRAFT_7)
-                && fieldsFromAllParts.containsKey(this.config.getKeyword(SchemaKeyword.TAG_REF))) {
+                && fieldsFromAllParts.containsKey(this.config.getKeyword(SchemaKeyword.TAG_REF))
+                && (schemaNode.size() > 1 || parts.size() > 1)) {
             // in Draft 7, any other attributes besides the $ref keyword were ignored
             return;
         }
         String ifTagName = this.config.getKeyword(SchemaKeyword.TAG_IF);
         for (Map.Entry<String, List<JsonNode>> fieldEntries : fieldsFromAllParts.entrySet()) {
-            if (fieldEntries.getValue().size() == 1) {
-                // no conflicts, no further checks
-                continue;
-            }
             if (ifTagName.equals(fieldEntries.getKey())) {
                 // "if"/"then"/"else" tags should remain isolated in their sub-schemas
                 return;
             }
+            if (fieldEntries.getValue().size() == 1) {
+                // no conflicts, no further checks
+                continue;
+            }
             int offset;
             if (!allOfTagName.equals(fieldEntries.getKey())) {
                 offset = 0;
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImpl.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImpl.java
index dbd37e3..9c6d99c 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImpl.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGenerationContextImpl.java
@@ -335,7 +335,9 @@ public class SchemaGenerationContextImpl implements SchemaGenerationContext {
         // always wrap subtype definitions, in order to avoid pointing at the same definition node as the super type
         SchemaKeyword arrayNodeName = subtypes.size() == 1 ? SchemaKeyword.TAG_ALLOF : SchemaKeyword.TAG_ANYOF;
         ArrayNode subtypeDefinitionArrayNode = definition.withArray(this.getKeyword(arrayNodeName));
-        subtypes.forEach(subtype -> this.traverseGenericType(subtype, subtypeDefinitionArrayNode.addObject(), false));
+        subtypes.stream()
+                .map(this::createDefinitionReference)
+                .forEach(subtypeDefinitionArrayNode::add);
         return true;
     }
 
@@ -553,7 +555,7 @@ public class SchemaGenerationContextImpl implements SchemaGenerationContext {
      */
     private ObjectNode populateFieldSchema(FieldScope field) {
         List<ResolvedType> typeOverrides = this.generatorConfig.resolveTargetTypeOverrides(field);
-        if (typeOverrides == null) {
+        if (typeOverrides == null && this.generatorConfig.shouldTransparentlyResolveSubtypesOfMembers()) {
             typeOverrides = this.generatorConfig.resolveSubtypes(field.getType(), this);
         }
         List<FieldScope> fieldOptions;
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java
index 1602f11..2da2069 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/impl/SchemaGeneratorConfigImpl.java
@@ -114,6 +114,11 @@ public class SchemaGeneratorConfigImpl implements SchemaGeneratorConfig {
         return this.isOptionEnabled(Option.DEFINITION_FOR_MAIN_SCHEMA);
     }
 
+    @Override
+    public boolean shouldTransparentlyResolveSubtypesOfMembers() {
+        return !this.isOptionEnabled(Option.DEFINITIONS_FOR_MEMBER_SUPERTYPES);
+    }
+
     @Override
     public boolean shouldInlineAllSchemas() {
         return this.isOptionEnabled(Option.INLINE_ALL_SCHEMAS);
@@ -191,9 +196,9 @@ public class SchemaGeneratorConfigImpl implements SchemaGeneratorConfig {
 
     @Override
     @SuppressWarnings("unchecked")
-    public <M extends MemberScope<?, ?>> CustomDefinition getCustomDefinition(M scope, SchemaGenerationContext context,
+    public <M extends MemberScope<?, ?>> CustomPropertyDefinition getCustomDefinition(M scope, SchemaGenerationContext context,
             CustomPropertyDefinitionProvider<M> ignoredDefinitionProvider) {
-        CustomDefinition result;
+        CustomPropertyDefinition result;
         if (scope instanceof FieldScope) {
             result = this.getCustomDefinition(this.fieldConfigPart, (FieldScope) scope, context,
                     (CustomPropertyDefinitionProvider<FieldScope>) ignoredDefinitionProvider);
@@ -203,9 +208,6 @@ public class SchemaGeneratorConfigImpl implements SchemaGeneratorConfig {
         } else {
             throw new IllegalArgumentException("Unexpected member scope: " + (scope == null ? null : scope.getClass().getName()));
         }
-        if (result == null) {
-            result = this.getCustomDefinition(scope.getType(), context, null);
-        }
         return result;
     }
 
@@ -225,9 +227,9 @@ public class SchemaGeneratorConfigImpl implements SchemaGeneratorConfig {
         final List<CustomPropertyDefinitionProvider<M>> providers = configPart.getCustomDefinitionProviders();
         CustomPropertyDefinition result;
         if (ignoredDefinitionProvider == null || providers.contains(ignoredDefinitionProvider)) {
-            int firstRelevantProviderIndex = 1 + providers.indexOf(ignoredDefinitionProvider);
-            result = providers.subList(firstRelevantProviderIndex, providers.size())
-                    .stream()
+            int providerCountToIgnore = 1 + providers.indexOf(ignoredDefinitionProvider);
+            result = providers.stream()
+                    .skip(providerCountToIgnore)
                     .map(provider -> provider.provideCustomSchemaDefinition(scope, context))
                     .filter(Objects::nonNull)
                     .findFirst()
@@ -242,9 +244,9 @@ public class SchemaGeneratorConfigImpl implements SchemaGeneratorConfig {
     public CustomDefinition getCustomDefinition(ResolvedType javaType, SchemaGenerationContext context,
             CustomDefinitionProviderV2 ignoredDefinitionProvider) {
         final List<CustomDefinitionProviderV2> providers = this.typesInGeneralConfigPart.getCustomDefinitionProviders();
-        int firstRelevantProviderIndex = 1 + providers.indexOf(ignoredDefinitionProvider);
-        return providers.subList(firstRelevantProviderIndex, providers.size())
-                .stream()
+        int providerCountToIgnore = 1 + providers.indexOf(ignoredDefinitionProvider);
+        return providers.stream()
+                .skip(providerCountToIgnore)
                 .map(provider -> provider.provideCustomSchemaDefinition(javaType, context))
                 .filter(Objects::nonNull)
                 .findFirst()
diff --git a/slate-docs/source/includes/_main-generator.md b/slate-docs/source/includes/_main-generator.md
index f2a9674..af2543b 100644
--- a/slate-docs/source/includes/_main-generator.md
+++ b/slate-docs/source/includes/_main-generator.md
@@ -284,6 +284,14 @@ configBuilder.without(
     </tr>
     <tr>
       <td rowspan="2" style="text-align: right">30</td>
+      <td colspan="2"><code>Option.DEFINITIONS_FOR_MEMBER_SUPERTYPES</code></td>
+    </tr>
+    <tr>
+      <td>For a member (field/method), having a declared type for which subtypes are being detected, include a single definition with any collected member attributes assigned directly. Any subtypes are only being handled as generic types, i.e., outside of the member context.</td>
+      <td>For a member (field/method), having a declared type for which subtypes are being detected, include a list of definittions: one for each subtype in the given member's context. This allows independently interpreting contextual information (e.g., member annotations) for each subtype.</td>
+    </tr>
+    <tr>
+      <td rowspan="2" style="text-align: right">31</td>
       <td colspan="2"><code>Option.INLINE_ALL_SCHEMAS</code></td>
     </tr>
     <tr>
@@ -291,7 +299,7 @@ configBuilder.without(
       <td>Depending on whether <code>DEFINITIONS_FOR_ALL_OBJECTS</code> is included or excluded.</td>
     </tr>
     <tr>
-      <td rowspan="2" style="text-align: right">31</td>
+      <td rowspan="2" style="text-align: right">32</td>
       <td colspan="2"><code>Option.PLAIN_DEFINITION_KEYS</code></td>
     </tr>
     <tr>
@@ -299,7 +307,7 @@ configBuilder.without(
       <td>Ensure that the keys for any <code>$defs</code>/<code>definitions</code> are URI compatible (as expected by the JSON Schema specification).</td>
     </tr>
     <tr>
-      <td rowspan="2" style="text-align: right">32</td>
+      <td rowspan="2" style="text-align: right">33</td>
       <td colspan="2"><code>Option.ALLOF_CLEANUP_AT_THE_END</code></td>
     </tr>
     <tr>
@@ -346,9 +354,10 @@ Below, you can find the lists of <code>Option</code>s included/excluded in the r
 | 27 | `FORBIDDEN_ADDITIONAL_PROPERTIES_BY_DEFAULT` | ⬜️ | ⬜️ | ⬜️ |
 | 28 | `DEFINITIONS_FOR_ALL_OBJECTS` | ⬜️ | ⬜️ | ⬜️ |
 | 29 | `DEFINITION_FOR_MAIN_SCHEMA` | ⬜️ | ⬜️ | ⬜️ |
-| 30 | `INLINE_ALL_SCHEMAS` | ⬜️ | ⬜️ | ⬜️ |
-| 31 | `PLAIN_DEFINITION_KEYS` | ⬜️ | ⬜️ | ⬜️ |
-| 32 | `ALLOF_CLEANUP_AT_THE_END` | ✅ | ✅ | ✅ |
+| 30 | `DEFINITIONS_FOR_MEMBER_SUPERTYPES` | ⬜️ | ⬜️ | ⬜️ |
+| 31 | `INLINE_ALL_SCHEMAS` | ⬜️ | ⬜️ | ⬜️ |
+| 32 | `PLAIN_DEFINITION_KEYS` | ⬜️ | ⬜️ | ⬜️ |
+| 33 | `ALLOF_CLEANUP_AT_THE_END` | ✅ | ✅ | ✅ |
 
 # Generator – Modules
 Similar to an `OptionPreset` being a short-cut to including various `Option`s, the concept of `Module`s is a convenient way of including multiple [individual configurations](#generator-individual-configurations) or even [advanced configurations](#generator-advanced-configurations) (as per the following sections) at once.


Test patch:
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorSubtypesTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorSubtypesTest.java
index eaa1fb0..6f590a5 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorSubtypesTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorSubtypesTest.java
@@ -49,7 +49,7 @@ public class SchemaGeneratorSubtypesTest {
     @MethodSource("parametersForTestGenerateSchema")
     public void testGenerateSchema(String caseTitle, List<Class<?>> subtypes, SchemaVersion schemaVersion) throws Exception {
         SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(schemaVersion, OptionPreset.PLAIN_JSON)
-                .with(Option.DEFINITIONS_FOR_ALL_OBJECTS, Option.NULLABLE_FIELDS_BY_DEFAULT);
+                .with(Option.DEFINITIONS_FOR_ALL_OBJECTS, Option.NULLABLE_FIELDS_BY_DEFAULT, Option.DEFINITIONS_FOR_MEMBER_SUPERTYPES);
         configBuilder.forTypesInGeneral()
                 .withSubtypeResolver(new TestSubtypeResolver(subtypes))
                 .withTitleResolver(TypeScope::getSimpleTypeDescription)
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-ONE_SUBTYPE_INVALID.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-ONE_SUBTYPE_INVALID.json
index 64f40cf..a5d194a 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-ONE_SUBTYPE_INVALID.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-ONE_SUBTYPE_INVALID.json
@@ -1,8 +1,8 @@
 {
     "$schema": "http://json-schema.org/draft-07/schema#",
     "definitions": {
-        "TestSubClass3-nullable": {
-            "type": ["object", "null"],
+        "TestSubClass3": {
+            "type": "object",
             "properties": {
                 "fieldInSubtype": {
                     "type": "integer",
@@ -25,6 +25,13 @@
             },
             "title": "TestSuperClass<Boolean>",
             "description": "supertype-only description"
+        },
+        "TestSuperClass(String)-nullable": {
+            "anyOf": [{
+                    "type": "null"
+                }, {
+                    "$ref": "#/definitions/TestSubClass3"
+                }]
         }
     },
     "type": "object",
@@ -44,7 +51,7 @@
                 }]
         },
         "stringSupertypeField": {
-            "$ref": "#/definitions/TestSubClass3-nullable"
+            "$ref": "#/definitions/TestSuperClass(String)-nullable"
         }
     },
     "title": "TestClassWithSuperTypeReferences"
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-ONE_SUBTYPE_VALID.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-ONE_SUBTYPE_VALID.json
index 7daff30..846318f 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-ONE_SUBTYPE_VALID.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-ONE_SUBTYPE_VALID.json
@@ -1,8 +1,8 @@
 {
     "$schema": "http://json-schema.org/draft-07/schema#",
     "definitions": {
-        "TestSubClass1(Boolean)-nullable": {
-            "type": ["object", "null"],
+        "TestSubClass1(Boolean)": {
+            "type": "object",
             "properties": {
                 "dependentGenericFieldInSubtype": {
                     "type": ["array", "null"],
@@ -23,8 +23,8 @@
             },
             "title": "TestSubClass1<Boolean>"
         },
-        "TestSubClass1(String)-nullable": {
-            "type": ["object", "null"],
+        "TestSubClass1(String)": {
+            "type": "object",
             "properties": {
                 "dependentGenericFieldInSubtype": {
                     "type": ["array", "null"],
@@ -44,12 +44,26 @@
                 }
             },
             "title": "TestSubClass1<String>"
+        },
+        "TestSuperClass(Boolean)-nullable": {
+            "anyOf": [{
+                    "type": "null"
+                }, {
+                    "$ref": "#/definitions/TestSubClass1(Boolean)"
+                }]
+        },
+        "TestSuperClass(String)-nullable": {
+            "anyOf": [{
+                    "type": "null"
+                }, {
+                    "$ref": "#/definitions/TestSubClass1(String)"
+                }]
         }
     },
     "type": "object",
     "properties": {
         "booleanSupertypeField": {
-            "$ref": "#/definitions/TestSubClass1(Boolean)-nullable"
+            "$ref": "#/definitions/TestSuperClass(Boolean)-nullable"
         },
         "numberOrStringObjectField": {
             "anyOf": [{
@@ -63,7 +77,7 @@
                 }]
         },
         "stringSupertypeField": {
-            "$ref": "#/definitions/TestSubClass1(String)-nullable"
+            "$ref": "#/definitions/TestSuperClass(String)-nullable"
         }
     },
     "title": "TestClassWithSuperTypeReferences"
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-THREE_SUBTYPES.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-THREE_SUBTYPES.json
index a7d7219..b749faa 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-THREE_SUBTYPES.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-THREE_SUBTYPES.json
@@ -86,11 +86,8 @@
                 }
             },
             "title": "TestSubClass3"
-        }
-    },
-    "type": "object",
-    "properties": {
-        "booleanSupertypeField": {
+        },
+        "TestSuperClass(Boolean)-nullable": {
             "anyOf": [{
                     "type": "null"
                 }, {
@@ -99,6 +96,23 @@
                     "$ref": "#/definitions/TestSubClass2(Boolean)"
                 }]
         },
+        "TestSuperClass(String)-nullable": {
+            "anyOf": [{
+                    "type": "null"
+                }, {
+                    "$ref": "#/definitions/TestSubClass1(String)"
+                }, {
+                    "$ref": "#/definitions/TestSubClass2(String)"
+                }, {
+                    "$ref": "#/definitions/TestSubClass3"
+                }]
+        }
+    },
+    "type": "object",
+    "properties": {
+        "booleanSupertypeField": {
+            "$ref": "#/definitions/TestSuperClass(Boolean)-nullable"
+        },
         "numberOrStringObjectField": {
             "anyOf": [{
                     "type": "null"
@@ -111,15 +125,7 @@
                 }]
         },
         "stringSupertypeField": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "$ref": "#/definitions/TestSubClass1(String)"
-                }, {
-                    "$ref": "#/definitions/TestSubClass2(String)"
-                }, {
-                    "$ref": "#/definitions/TestSubClass3"
-                }]
+            "$ref": "#/definitions/TestSuperClass(String)-nullable"
         }
     },
     "title": "TestClassWithSuperTypeReferences"
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-TWO_SUBTYPES.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-TWO_SUBTYPES.json
index 4e43a5c..9644be7 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-TWO_SUBTYPES.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass-withsupertypereferences-TWO_SUBTYPES.json
@@ -1,8 +1,8 @@
 {
     "$schema": "http://json-schema.org/draft-07/schema#",
     "definitions": {
-        "TestSubClass2(Boolean)-nullable": {
-            "type": ["object", "null"],
+        "TestSubClass2(Boolean)": {
+            "type": "object",
             "properties": {
                 "genericFieldInSupertype": {
                     "type": ["boolean", "null"],
@@ -42,12 +42,28 @@
                 }
             },
             "title": "TestSubClass3"
+        },
+        "TestSuperClass(Boolean)-nullable": {
+            "anyOf": [{
+                    "type": "null"
+                }, {
+                    "$ref": "#/definitions/TestSubClass2(Boolean)"
+                }]
+        },
+        "TestSuperClass(String)-nullable": {
+            "anyOf": [{
+                    "type": "null"
+                }, {
+                    "$ref": "#/definitions/TestSubClass2(String)"
+                }, {
+                    "$ref": "#/definitions/TestSubClass3"
+                }]
         }
     },
     "type": "object",
     "properties": {
         "booleanSupertypeField": {
-            "$ref": "#/definitions/TestSubClass2(Boolean)-nullable"
+            "$ref": "#/definitions/TestSuperClass(Boolean)-nullable"
         },
         "numberOrStringObjectField": {
             "anyOf": [{
@@ -61,13 +77,7 @@
                 }]
         },
         "stringSupertypeField": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "$ref": "#/definitions/TestSubClass2(String)"
-                }, {
-                    "$ref": "#/definitions/TestSubClass3"
-                }]
+            "$ref": "#/definitions/TestSuperClass(String)-nullable"
         }
     },
     "title": "TestClassWithSuperTypeReferences"
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-FULL_DOCUMENTATION-typeattributes.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-FULL_DOCUMENTATION-typeattributes.json
index ce755fd..b559655 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-FULL_DOCUMENTATION-typeattributes.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-FULL_DOCUMENTATION-typeattributes.json
@@ -2,19 +2,15 @@
     "type": "object",
     "properties": {
         "genericValue": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "type": "string",
-                    "$anchor": "#anchor",
-                    "title": "String",
-                    "description": "for type in general: String",
-                    "const": "constant string value",
-                    "minLength": 1,
-                    "maxLength": 256,
-                    "format": "date",
-                    "pattern": "^.{1,256}$"
-                }]
+            "type": ["string", "null"],
+            "$anchor": "#anchor",
+            "title": "String",
+            "description": "for type in general: String",
+            "const": "constant string value",
+            "minLength": 1,
+            "maxLength": 256,
+            "format": "date",
+            "pattern": "^.{1,256}$"
         },
         "genericArray": {
             "type": ["array", "null"],
@@ -42,29 +38,25 @@
             "description": "for type in general: int"
         },
         "ignoredInternalValue": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "type": "integer",
-                    "$anchor": "#anchor",
-                    "title": "Integer",
-                    "description": "for type in general: Integer",
-                    "default": 1,
-                    "enum": [1, 2, 3, 4, 5],
-                    "minimum": 1,
-                    "exclusiveMinimum": 0,
-                    "maximum": 10,
-                    "exclusiveMaximum": 11,
-                    "multipleOf": 1
-                }]
+            "type": ["integer", "null"],
+            "$anchor": "#anchor",
+            "title": "Integer",
+            "description": "for type in general: Integer",
+            "default": 1,
+            "enum": [1, 2, 3, 4, 5],
+            "minimum": 1,
+            "exclusiveMinimum": 0,
+            "maximum": 10,
+            "exclusiveMaximum": 11,
+            "multipleOf": 1
         },
-        "calculateSomething(Number, Number)": false,
         "getPrimitiveValue()": {
             "type": "integer",
             "$anchor": "#anchor",
             "title": "int",
             "description": "for type in general: int"
         },
+        "calculateSomething(Number, Number)": false,
         "isSimpleTestClass()": {
             "type": "boolean",
             "$anchor": "#anchor",
@@ -72,23 +64,18 @@
             "description": "for type in general: boolean"
         },
         "getGenericValue()": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "type": "string",
-                    "$anchor": "#anchor",
-                    "title": "String",
-                    "description": "for type in general: String",
-                    "const": "constant string value",
-                    "minLength": 1,
-                    "maxLength": 256,
-                    "format": "date",
-                    "pattern": "^.{1,256}$"
-                }]
+            "type": ["string", "null"],
+            "$anchor": "#anchor",
+            "title": "String",
+            "description": "for type in general: String",
+            "const": "constant string value",
+            "minLength": 1,
+            "maxLength": 256,
+            "format": "date",
+            "pattern": "^.{1,256}$"
         },
         "CONSTANT": {
             "type": "integer",
-            "const": 5,
             "$anchor": "#anchor",
             "title": "Long",
             "description": "for type in general: Long",
@@ -98,7 +85,8 @@
             "exclusiveMinimum": 0,
             "maximum": 10,
             "exclusiveMaximum": 11,
-            "multipleOf": 1
+            "multipleOf": 1,
+            "const": 5
         }
     },
     "$id": "id-TestClass1",
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-JAVA_OBJECT-methodattributes.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-JAVA_OBJECT-methodattributes.json
index d04160f..4f61dbf 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-JAVA_OBJECT-methodattributes.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-JAVA_OBJECT-methodattributes.json
@@ -12,18 +12,14 @@
             }
         },
         "genericValue": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "type": "string",
-                    "title": "String",
-                    "description": "looked-up from method: String",
-                    "const": "constant string value",
-                    "minLength": 1,
-                    "maxLength": 256,
-                    "format": "date",
-                    "pattern": "^.{1,256}$"
-                }]
+            "type": ["string", "null"],
+            "title": "String",
+            "description": "looked-up from method: String",
+            "const": "constant string value",
+            "minLength": 1,
+            "maxLength": 256,
+            "format": "date",
+            "pattern": "^.{1,256}$"
         },
         "primitiveValue": {
             "type": ["integer", "null"],
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-PLAIN_JSON-fieldattributes.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-PLAIN_JSON-fieldattributes.json
index fd4a594..21cd82c 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-PLAIN_JSON-fieldattributes.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass1-PLAIN_JSON-fieldattributes.json
@@ -10,49 +10,37 @@
             "uniqueItems": false,
             "type": ["array", "null"],
             "items": {
-                "anyOf": [{
-                        "type": "null"
-                    }, {
-                        "type": "string",
-                        "title": "String",
-                        "description": "looked-up from field: String",
-                        "const": "constant string value",
-                        "minLength": 1,
-                        "maxLength": 256,
-                        "format": "date",
-                        "pattern": "^.{1,256}$"
-                    }]
+                "type": ["string", "null"],
+                "title": "String",
+                "description": "looked-up from field: String",
+                "const": "constant string value",
+                "minLength": 1,
+                "maxLength": 256,
+                "format": "date",
+                "pattern": "^.{1,256}$"
             }
         },
         "genericValue": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "type": "string",
-                    "title": "String",
-                    "description": "looked-up from field: String",
-                    "const": "constant string value",
-                    "minLength": 1,
-                    "maxLength": 256,
-                    "format": "date",
-                    "pattern": "^.{1,256}$"
-                }]
+            "type": ["string", "null"],
+            "title": "String",
+            "description": "looked-up from field: String",
+            "const": "constant string value",
+            "minLength": 1,
+            "maxLength": 256,
+            "format": "date",
+            "pattern": "^.{1,256}$"
         },
         "ignoredInternalValue": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "type": "integer",
-                    "title": "Integer",
-                    "description": "looked-up from field: Integer",
-                    "default": 1,
-                    "enum": [1, 2, 3, 4, 5],
-                    "minimum": 1,
-                    "exclusiveMinimum": 0,
-                    "maximum": 10,
-                    "exclusiveMaximum": 11,
-                    "multipleOf": 1
-                }]
+            "type": ["integer", "null"],
+            "title": "Integer",
+            "description": "looked-up from field: Integer",
+            "default": 1,
+            "enum": [1, 2, 3, 4, 5],
+            "minimum": 1,
+            "exclusiveMinimum": 0,
+            "maximum": 10,
+            "exclusiveMaximum": 11,
+            "multipleOf": 1
         },
         "primitiveValue": {
             "type": ["integer", "null"],
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-FULL_DOCUMENTATION-typeattributes.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-FULL_DOCUMENTATION-typeattributes.json
index 83f26bc..501e8c7 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-FULL_DOCUMENTATION-typeattributes.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-FULL_DOCUMENTATION-typeattributes.json
@@ -4,19 +4,15 @@
             "type": "object",
             "properties": {
                 "get()": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "string",
-                            "$anchor": "#anchor",
-                            "title": "String",
-                            "description": "for type in general: String",
-                            "const": "constant string value",
-                            "minLength": 1,
-                            "maxLength": 256,
-                            "format": "date",
-                            "pattern": "^.{1,256}$"
-                        }]
+                    "type": ["string", "null"],
+                    "$anchor": "#anchor",
+                    "title": "String",
+                    "description": "for type in general: String",
+                    "const": "constant string value",
+                    "minLength": 1,
+                    "maxLength": 256,
+                    "format": "date",
+                    "pattern": "^.{1,256}$"
                 }
             },
             "$anchor": "#anchor",
@@ -27,22 +23,18 @@
         "Optional(Integer)": {
             "type": "object",
             "properties": {
-                "orElse(Integer)": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "$anchor": "#anchor",
-                            "title": "Integer",
-                            "description": "for type in general: Integer",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                "get()": {
+                    "type": ["integer", "null"],
+                    "$anchor": "#anchor",
+                    "title": "Integer",
+                    "description": "for type in general: Integer",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 },
                 "isPresent()": {
                     "type": "boolean",
@@ -50,22 +42,18 @@
                     "title": "boolean",
                     "description": "for type in general: boolean"
                 },
-                "get()": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "$anchor": "#anchor",
-                            "title": "Integer",
-                            "description": "for type in general: Integer",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                "orElse(Integer)": {
+                    "type": ["integer", "null"],
+                    "$anchor": "#anchor",
+                    "title": "Integer",
+                    "description": "for type in general: Integer",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 }
             },
             "$anchor": "#anchor",
@@ -84,19 +72,15 @@
             "type": "object",
             "properties": {
                 "name": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "string",
-                            "$anchor": "#anchor",
-                            "title": "String",
-                            "description": "for type in general: String",
-                            "const": "constant string value",
-                            "minLength": 1,
-                            "maxLength": 256,
-                            "format": "date",
-                            "pattern": "^.{1,256}$"
-                        }]
+                    "type": ["string", "null"],
+                    "$anchor": "#anchor",
+                    "title": "String",
+                    "description": "for type in general: String",
+                    "const": "constant string value",
+                    "minLength": 1,
+                    "maxLength": 256,
+                    "format": "date",
+                    "pattern": "^.{1,256}$"
                 },
                 "ordinal": {
                     "type": "integer",
@@ -112,7 +96,6 @@
                 },
                 "name()": {
                     "type": "string",
-                    "enum": ["UP", "DOWN", "CEILING", "FLOOR", "HALF_UP", "HALF_DOWN", "HALF_EVEN", "UNNECESSARY"],
                     "$anchor": "#anchor",
                     "title": "String",
                     "description": "for type in general: String",
@@ -120,7 +103,8 @@
                     "minLength": 1,
                     "maxLength": 256,
                     "format": "date",
-                    "pattern": "^.{1,256}$"
+                    "pattern": "^.{1,256}$",
+                    "enum": ["UP", "DOWN", "CEILING", "FLOOR", "HALF_UP", "HALF_DOWN", "HALF_EVEN", "UNNECESSARY"]
                 },
                 "compareTo(RoundingMode)": {
                     "type": "integer",
@@ -162,21 +146,17 @@
             "type": ["object", "null"],
             "properties": {
                 "get()": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "$anchor": "#anchor",
-                            "title": "Integer",
-                            "description": "for type in general: Integer",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "$anchor": "#anchor",
+                    "title": "Integer",
+                    "description": "for type in general: Integer",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 }
             },
             "$anchor": "#anchor",
@@ -188,19 +168,15 @@
             "type": "object",
             "properties": {
                 "genericValue": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "string",
-                            "$anchor": "#anchor",
-                            "title": "String",
-                            "description": "for type in general: String",
-                            "const": "constant string value",
-                            "minLength": 1,
-                            "maxLength": 256,
-                            "format": "date",
-                            "pattern": "^.{1,256}$"
-                        }]
+                    "type": ["string", "null"],
+                    "$anchor": "#anchor",
+                    "title": "String",
+                    "description": "for type in general: String",
+                    "const": "constant string value",
+                    "minLength": 1,
+                    "maxLength": 256,
+                    "format": "date",
+                    "pattern": "^.{1,256}$"
                 },
                 "genericArray": {
                     "type": ["array", "null"],
@@ -228,29 +204,25 @@
                     "description": "for type in general: int"
                 },
                 "ignoredInternalValue": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "$anchor": "#anchor",
-                            "title": "Integer",
-                            "description": "for type in general: Integer",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "$anchor": "#anchor",
+                    "title": "Integer",
+                    "description": "for type in general: Integer",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 },
-                "calculateSomething(Number, Number)": false,
                 "getPrimitiveValue()": {
                     "type": "integer",
                     "$anchor": "#anchor",
                     "title": "int",
                     "description": "for type in general: int"
                 },
+                "calculateSomething(Number, Number)": false,
                 "isSimpleTestClass()": {
                     "type": "boolean",
                     "$anchor": "#anchor",
@@ -258,23 +230,18 @@
                     "description": "for type in general: boolean"
                 },
                 "getGenericValue()": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "string",
-                            "$anchor": "#anchor",
-                            "title": "String",
-                            "description": "for type in general: String",
-                            "const": "constant string value",
-                            "minLength": 1,
-                            "maxLength": 256,
-                            "format": "date",
-                            "pattern": "^.{1,256}$"
-                        }]
+                    "type": ["string", "null"],
+                    "$anchor": "#anchor",
+                    "title": "String",
+                    "description": "for type in general: String",
+                    "const": "constant string value",
+                    "minLength": 1,
+                    "maxLength": 256,
+                    "format": "date",
+                    "pattern": "^.{1,256}$"
                 },
                 "CONSTANT": {
                     "type": "integer",
-                    "const": 5,
                     "$anchor": "#anchor",
                     "title": "Long",
                     "description": "for type in general: Long",
@@ -284,7 +251,8 @@
                     "exclusiveMinimum": 0,
                     "maximum": 10,
                     "exclusiveMaximum": 11,
-                    "multipleOf": 1
+                    "multipleOf": 1,
+                    "const": 5
                 }
             },
             "$id": "id-TestClass1",
@@ -310,21 +278,17 @@
             "type": "object",
             "properties": {
                 "genericValue": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "$anchor": "#anchor",
-                            "title": "Long",
-                            "description": "for type in general: Long",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "$anchor": "#anchor",
+                    "title": "Long",
+                    "description": "for type in general: Long",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 },
                 "genericArray": {
                     "type": ["array", "null"],
@@ -348,21 +312,17 @@
                     "uniqueItems": false
                 },
                 "getGenericValue()": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "$anchor": "#anchor",
-                            "title": "Long",
-                            "description": "for type in general: Long",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "$anchor": "#anchor",
+                    "title": "Long",
+                    "description": "for type in general: Long",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 }
             },
             "$id": "id-TestClass2<Long>",
@@ -397,19 +357,15 @@
             "type": "object",
             "properties": {
                 "genericValue": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "string",
-                            "$anchor": "#anchor",
-                            "title": "String",
-                            "description": "for type in general: String",
-                            "const": "constant string value",
-                            "minLength": 1,
-                            "maxLength": 256,
-                            "format": "date",
-                            "pattern": "^.{1,256}$"
-                        }]
+                    "type": ["string", "null"],
+                    "$anchor": "#anchor",
+                    "title": "String",
+                    "description": "for type in general: String",
+                    "const": "constant string value",
+                    "minLength": 1,
+                    "maxLength": 256,
+                    "format": "date",
+                    "pattern": "^.{1,256}$"
                 },
                 "genericArray": {
                     "type": ["array", "null"],
@@ -431,19 +387,15 @@
                     "uniqueItems": false
                 },
                 "getGenericValue()": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "string",
-                            "$anchor": "#anchor",
-                            "title": "String",
-                            "description": "for type in general: String",
-                            "const": "constant string value",
-                            "minLength": 1,
-                            "maxLength": 256,
-                            "format": "date",
-                            "pattern": "^.{1,256}$"
-                        }]
+                    "type": ["string", "null"],
+                    "$anchor": "#anchor",
+                    "title": "String",
+                    "description": "for type in general: String",
+                    "const": "constant string value",
+                    "minLength": 1,
+                    "maxLength": 256,
+                    "format": "date",
+                    "pattern": "^.{1,256}$"
                 }
             },
             "$id": "id-TestClass2<String>",
@@ -659,6 +611,9 @@
         "class4": {
             "$ref": "#/definitions/TestClass4(Integer,String)-nullable"
         },
+        "getClass4()": {
+            "$ref": "#/definitions/TestClass4(Integer,String)-nullable"
+        },
         "getNestedLong()": {
             "$ref": "#/definitions/TestClass2(Long)-nullable"
         },
@@ -676,9 +631,6 @@
             "minItems": 2,
             "maxItems": 100,
             "uniqueItems": false
-        },
-        "getClass4()": {
-            "$ref": "#/definitions/TestClass4(Integer,String)-nullable"
         }
     },
     "$id": "id-TestClass3",
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-JAVA_OBJECT-methodattributes.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-JAVA_OBJECT-methodattributes.json
index b7b7c10..62e2960 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-JAVA_OBJECT-methodattributes.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-JAVA_OBJECT-methodattributes.json
@@ -9,36 +9,28 @@
                     "description": "looked-up from method: boolean"
                 },
                 "get()": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "title": "Integer",
-                            "description": "looked-up from method: Integer",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "title": "Integer",
+                    "description": "looked-up from method: Integer",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 },
                 "orElse(Integer)": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "title": "Integer",
-                            "description": "looked-up from method: Integer",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "title": "Integer",
+                    "description": "looked-up from method: Integer",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 }
             }
         },
@@ -51,19 +43,15 @@
                     "description": "looked-up from method: int"
                 },
                 "name()": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "string",
-                            "title": "String",
-                            "description": "looked-up from method: String",
-                            "const": "constant string value",
-                            "readOnly": true,
-                            "minLength": 1,
-                            "maxLength": 256,
-                            "format": "date",
-                            "pattern": "^.{1,256}$"
-                        }]
+                    "type": ["string", "null"],
+                    "title": "String",
+                    "description": "looked-up from method: String",
+                    "const": "constant string value",
+                    "readOnly": true,
+                    "minLength": 1,
+                    "maxLength": 256,
+                    "format": "date",
+                    "pattern": "^.{1,256}$"
                 },
                 "valueOf(String)": {
                     "allOf": [{
@@ -120,18 +108,14 @@
                     }
                 },
                 "genericValue": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "string",
-                            "title": "String",
-                            "description": "looked-up from method: String",
-                            "const": "constant string value",
-                            "minLength": 1,
-                            "maxLength": 256,
-                            "format": "date",
-                            "pattern": "^.{1,256}$"
-                        }]
+                    "type": ["string", "null"],
+                    "title": "String",
+                    "description": "looked-up from method: String",
+                    "const": "constant string value",
+                    "minLength": 1,
+                    "maxLength": 256,
+                    "format": "date",
+                    "pattern": "^.{1,256}$"
                 },
                 "primitiveValue": {
                     "type": ["integer", "null"],
@@ -156,20 +140,16 @@
                     }
                 },
                 "genericValue": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "title": "Long",
-                            "description": "looked-up from method: Long",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "title": "Long",
+                    "description": "looked-up from method: Long",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 }
             }
         },
@@ -183,18 +163,14 @@
                     }
                 },
                 "genericValue": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "string",
-                            "title": "String",
-                            "description": "looked-up from method: String",
-                            "const": "constant string value",
-                            "minLength": 1,
-                            "maxLength": 256,
-                            "format": "date",
-                            "pattern": "^.{1,256}$"
-                        }]
+                    "type": ["string", "null"],
+                    "title": "String",
+                    "description": "looked-up from method: String",
+                    "const": "constant string value",
+                    "minLength": 1,
+                    "maxLength": 256,
+                    "format": "date",
+                    "pattern": "^.{1,256}$"
                 }
             }
         }
@@ -260,18 +236,14 @@
                         "type": "object",
                         "properties": {
                             "get()": {
-                                "anyOf": [{
-                                        "type": "null"
-                                    }, {
-                                        "type": "string",
-                                        "title": "String",
-                                        "description": "looked-up from method: String",
-                                        "const": "constant string value",
-                                        "minLength": 1,
-                                        "maxLength": 256,
-                                        "format": "date",
-                                        "pattern": "^.{1,256}$"
-                                    }]
+                                "type": ["string", "null"],
+                                "title": "String",
+                                "description": "looked-up from method: String",
+                                "const": "constant string value",
+                                "minLength": 1,
+                                "maxLength": 256,
+                                "format": "date",
+                                "pattern": "^.{1,256}$"
                             }
                         }
                     }
@@ -280,20 +252,16 @@
                     "type": "object",
                     "properties": {
                         "get()": {
-                            "anyOf": [{
-                                    "type": "null"
-                                }, {
-                                    "type": "integer",
-                                    "title": "Integer",
-                                    "description": "looked-up from method: Integer",
-                                    "default": 1,
-                                    "enum": [1, 2, 3, 4, 5],
-                                    "minimum": 1,
-                                    "exclusiveMinimum": 0,
-                                    "maximum": 10,
-                                    "exclusiveMaximum": 11,
-                                    "multipleOf": 1
-                                }]
+                            "type": ["integer", "null"],
+                            "title": "Integer",
+                            "description": "looked-up from method: Integer",
+                            "default": 1,
+                            "enum": [1, 2, 3, 4, 5],
+                            "minimum": 1,
+                            "exclusiveMinimum": 0,
+                            "maximum": 10,
+                            "exclusiveMaximum": 11,
+                            "multipleOf": 1
                         }
                     }
                 }
diff --git a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-PLAIN_JSON-fieldattributes.json b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-PLAIN_JSON-fieldattributes.json
index 21c2a67..b861440 100644
--- a/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-PLAIN_JSON-fieldattributes.json
+++ b/jsonschema-generator/src/test/resources/com/github/victools/jsonschema/generator/testclass3-PLAIN_JSON-fieldattributes.json
@@ -26,33 +26,25 @@
                                         "uniqueItems": false,
                                         "type": ["array", "null"],
                                         "items": {
-                                            "anyOf": [{
-                                                    "type": "null"
-                                                }, {
-                                                    "type": "string",
-                                                    "title": "String",
-                                                    "description": "looked-up from field: String",
-                                                    "const": "constant string value",
-                                                    "minLength": 1,
-                                                    "maxLength": 256,
-                                                    "format": "date",
-                                                    "pattern": "^.{1,256}$"
-                                                }]
+                                            "type": ["string", "null"],
+                                            "title": "String",
+                                            "description": "looked-up from field: String",
+                                            "const": "constant string value",
+                                            "minLength": 1,
+                                            "maxLength": 256,
+                                            "format": "date",
+                                            "pattern": "^.{1,256}$"
                                         }
                                     },
                                     "genericValue": {
-                                        "anyOf": [{
-                                                "type": "null"
-                                            }, {
-                                                "type": "string",
-                                                "title": "String",
-                                                "description": "looked-up from field: String",
-                                                "const": "constant string value",
-                                                "minLength": 1,
-                                                "maxLength": 256,
-                                                "format": "date",
-                                                "pattern": "^.{1,256}$"
-                                            }]
+                                        "type": ["string", "null"],
+                                        "title": "String",
+                                        "description": "looked-up from field: String",
+                                        "const": "constant string value",
+                                        "minLength": 1,
+                                        "maxLength": 256,
+                                        "format": "date",
+                                        "pattern": "^.{1,256}$"
                                     }
                                 },
                                 "title": "TestClass2<String>",
@@ -76,33 +68,25 @@
                                     "uniqueItems": false,
                                     "type": ["array", "null"],
                                     "items": {
-                                        "anyOf": [{
-                                                "type": "null"
-                                            }, {
-                                                "type": "string",
-                                                "title": "String",
-                                                "description": "looked-up from field: String",
-                                                "const": "constant string value",
-                                                "minLength": 1,
-                                                "maxLength": 256,
-                                                "format": "date",
-                                                "pattern": "^.{1,256}$"
-                                            }]
+                                        "type": ["string", "null"],
+                                        "title": "String",
+                                        "description": "looked-up from field: String",
+                                        "const": "constant string value",
+                                        "minLength": 1,
+                                        "maxLength": 256,
+                                        "format": "date",
+                                        "pattern": "^.{1,256}$"
                                     }
                                 },
                                 "genericValue": {
-                                    "anyOf": [{
-                                            "type": "null"
-                                        }, {
-                                            "type": "string",
-                                            "title": "String",
-                                            "description": "looked-up from field: String",
-                                            "const": "constant string value",
-                                            "minLength": 1,
-                                            "maxLength": 256,
-                                            "format": "date",
-                                            "pattern": "^.{1,256}$"
-                                        }]
+                                    "type": ["string", "null"],
+                                    "title": "String",
+                                    "description": "looked-up from field: String",
+                                    "const": "constant string value",
+                                    "minLength": 1,
+                                    "maxLength": 256,
+                                    "format": "date",
+                                    "pattern": "^.{1,256}$"
                                 }
                             },
                             "title": "TestClass2<String>",
@@ -130,33 +114,25 @@
                                     "uniqueItems": false,
                                     "type": ["array", "null"],
                                     "items": {
-                                        "anyOf": [{
-                                                "type": "null"
-                                            }, {
-                                                "type": "string",
-                                                "title": "String",
-                                                "description": "looked-up from field: String",
-                                                "const": "constant string value",
-                                                "minLength": 1,
-                                                "maxLength": 256,
-                                                "format": "date",
-                                                "pattern": "^.{1,256}$"
-                                            }]
+                                        "type": ["string", "null"],
+                                        "title": "String",
+                                        "description": "looked-up from field: String",
+                                        "const": "constant string value",
+                                        "minLength": 1,
+                                        "maxLength": 256,
+                                        "format": "date",
+                                        "pattern": "^.{1,256}$"
                                     }
                                 },
                                 "genericValue": {
-                                    "anyOf": [{
-                                            "type": "null"
-                                        }, {
-                                            "type": "string",
-                                            "title": "String",
-                                            "description": "looked-up from field: String",
-                                            "const": "constant string value",
-                                            "minLength": 1,
-                                            "maxLength": 256,
-                                            "format": "date",
-                                            "pattern": "^.{1,256}$"
-                                        }]
+                                    "type": ["string", "null"],
+                                    "title": "String",
+                                    "description": "looked-up from field: String",
+                                    "const": "constant string value",
+                                    "minLength": 1,
+                                    "maxLength": 256,
+                                    "format": "date",
+                                    "pattern": "^.{1,256}$"
                                 }
                             }
                         }
@@ -170,37 +146,29 @@
                     "uniqueItems": false,
                     "type": ["array", "null"],
                     "items": {
-                        "anyOf": [{
-                                "type": "null"
-                            }, {
-                                "type": "integer",
-                                "title": "Integer",
-                                "description": "looked-up from field: Integer",
-                                "default": 1,
-                                "enum": [1, 2, 3, 4, 5],
-                                "minimum": 1,
-                                "exclusiveMinimum": 0,
-                                "maximum": 10,
-                                "exclusiveMaximum": 11,
-                                "multipleOf": 1
-                            }]
+                        "type": ["integer", "null"],
+                        "title": "Integer",
+                        "description": "looked-up from field: Integer",
+                        "default": 1,
+                        "enum": [1, 2, 3, 4, 5],
+                        "minimum": 1,
+                        "exclusiveMinimum": 0,
+                        "maximum": 10,
+                        "exclusiveMaximum": 11,
+                        "multipleOf": 1
                     }
                 },
                 "optionalS": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "title": "Integer",
-                            "description": "looked-up from field: Integer",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "title": "Integer",
+                    "description": "looked-up from field: Integer",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 },
                 "setOfStringSupplier": {
                     "title": "Set<LazyStringSupplier>",
@@ -210,35 +178,27 @@
                     "uniqueItems": false,
                     "type": ["array", "null"],
                     "items": {
-                        "anyOf": [{
-                                "type": "null"
-                            }, {
-                                "type": "string",
-                                "title": "String",
-                                "description": "looked-up from field: String",
-                                "const": "constant string value",
-                                "minLength": 1,
-                                "maxLength": 256,
-                                "format": "date",
-                                "pattern": "^.{1,256}$"
-                            }]
+                        "type": ["string", "null"],
+                        "title": "String",
+                        "description": "looked-up from field: String",
+                        "const": "constant string value",
+                        "minLength": 1,
+                        "maxLength": 256,
+                        "format": "date",
+                        "pattern": "^.{1,256}$"
                     }
                 },
                 "supplierS": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "title": "Integer",
-                            "description": "looked-up from field: Integer",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "title": "Integer",
+                    "description": "looked-up from field: Integer",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 }
             },
             "title": "TestClass4<Integer, String>",
@@ -276,49 +236,37 @@
                                     "uniqueItems": false,
                                     "type": ["array", "null"],
                                     "items": {
-                                        "anyOf": [{
-                                                "type": "null"
-                                            }, {
-                                                "type": "string",
-                                                "title": "String",
-                                                "description": "looked-up from field: String",
-                                                "const": "constant string value",
-                                                "minLength": 1,
-                                                "maxLength": 256,
-                                                "format": "date",
-                                                "pattern": "^.{1,256}$"
-                                            }]
+                                        "type": ["string", "null"],
+                                        "title": "String",
+                                        "description": "looked-up from field: String",
+                                        "const": "constant string value",
+                                        "minLength": 1,
+                                        "maxLength": 256,
+                                        "format": "date",
+                                        "pattern": "^.{1,256}$"
                                     }
                                 },
                                 "genericValue": {
-                                    "anyOf": [{
-                                            "type": "null"
-                                        }, {
-                                            "type": "string",
-                                            "title": "String",
-                                            "description": "looked-up from field: String",
-                                            "const": "constant string value",
-                                            "minLength": 1,
-                                            "maxLength": 256,
-                                            "format": "date",
-                                            "pattern": "^.{1,256}$"
-                                        }]
+                                    "type": ["string", "null"],
+                                    "title": "String",
+                                    "description": "looked-up from field: String",
+                                    "const": "constant string value",
+                                    "minLength": 1,
+                                    "maxLength": 256,
+                                    "format": "date",
+                                    "pattern": "^.{1,256}$"
                                 },
                                 "ignoredInternalValue": {
-                                    "anyOf": [{
-                                            "type": "null"
-                                        }, {
-                                            "type": "integer",
-                                            "title": "Integer",
-                                            "description": "looked-up from field: Integer",
-                                            "default": 1,
-                                            "enum": [1, 2, 3, 4, 5],
-                                            "minimum": 1,
-                                            "exclusiveMinimum": 0,
-                                            "maximum": 10,
-                                            "exclusiveMaximum": 11,
-                                            "multipleOf": 1
-                                        }]
+                                    "type": ["integer", "null"],
+                                    "title": "Integer",
+                                    "description": "looked-up from field: Integer",
+                                    "default": 1,
+                                    "enum": [1, 2, 3, 4, 5],
+                                    "minimum": 1,
+                                    "exclusiveMinimum": 0,
+                                    "maximum": 10,
+                                    "exclusiveMaximum": 11,
+                                    "multipleOf": 1
                                 },
                                 "primitiveValue": {
                                     "type": ["integer", "null"],
@@ -347,49 +295,37 @@
                                 "uniqueItems": false,
                                 "type": ["array", "null"],
                                 "items": {
-                                    "anyOf": [{
-                                            "type": "null"
-                                        }, {
-                                            "type": "string",
-                                            "title": "String",
-                                            "description": "looked-up from field: String",
-                                            "const": "constant string value",
-                                            "minLength": 1,
-                                            "maxLength": 256,
-                                            "format": "date",
-                                            "pattern": "^.{1,256}$"
-                                        }]
+                                    "type": ["string", "null"],
+                                    "title": "String",
+                                    "description": "looked-up from field: String",
+                                    "const": "constant string value",
+                                    "minLength": 1,
+                                    "maxLength": 256,
+                                    "format": "date",
+                                    "pattern": "^.{1,256}$"
                                 }
                             },
                             "genericValue": {
-                                "anyOf": [{
-                                        "type": "null"
-                                    }, {
-                                        "type": "string",
-                                        "title": "String",
-                                        "description": "looked-up from field: String",
-                                        "const": "constant string value",
-                                        "minLength": 1,
-                                        "maxLength": 256,
-                                        "format": "date",
-                                        "pattern": "^.{1,256}$"
-                                    }]
+                                "type": ["string", "null"],
+                                "title": "String",
+                                "description": "looked-up from field: String",
+                                "const": "constant string value",
+                                "minLength": 1,
+                                "maxLength": 256,
+                                "format": "date",
+                                "pattern": "^.{1,256}$"
                             },
                             "ignoredInternalValue": {
-                                "anyOf": [{
-                                        "type": "null"
-                                    }, {
-                                        "type": "integer",
-                                        "title": "Integer",
-                                        "description": "looked-up from field: Integer",
-                                        "default": 1,
-                                        "enum": [1, 2, 3, 4, 5],
-                                        "minimum": 1,
-                                        "exclusiveMinimum": 0,
-                                        "maximum": 10,
-                                        "exclusiveMaximum": 11,
-                                        "multipleOf": 1
-                                    }]
+                                "type": ["integer", "null"],
+                                "title": "Integer",
+                                "description": "looked-up from field: Integer",
+                                "default": 1,
+                                "enum": [1, 2, 3, 4, 5],
+                                "minimum": 1,
+                                "exclusiveMinimum": 0,
+                                "maximum": 10,
+                                "exclusiveMaximum": 11,
+                                "multipleOf": 1
                             },
                             "primitiveValue": {
                                 "type": ["integer", "null"],
@@ -425,49 +361,37 @@
                                 "uniqueItems": false,
                                 "type": ["array", "null"],
                                 "items": {
-                                    "anyOf": [{
-                                            "type": "null"
-                                        }, {
-                                            "type": "string",
-                                            "title": "String",
-                                            "description": "looked-up from field: String",
-                                            "const": "constant string value",
-                                            "minLength": 1,
-                                            "maxLength": 256,
-                                            "format": "date",
-                                            "pattern": "^.{1,256}$"
-                                        }]
+                                    "type": ["string", "null"],
+                                    "title": "String",
+                                    "description": "looked-up from field: String",
+                                    "const": "constant string value",
+                                    "minLength": 1,
+                                    "maxLength": 256,
+                                    "format": "date",
+                                    "pattern": "^.{1,256}$"
                                 }
                             },
                             "genericValue": {
-                                "anyOf": [{
-                                        "type": "null"
-                                    }, {
-                                        "type": "string",
-                                        "title": "String",
-                                        "description": "looked-up from field: String",
-                                        "const": "constant string value",
-                                        "minLength": 1,
-                                        "maxLength": 256,
-                                        "format": "date",
-                                        "pattern": "^.{1,256}$"
-                                    }]
+                                "type": ["string", "null"],
+                                "title": "String",
+                                "description": "looked-up from field: String",
+                                "const": "constant string value",
+                                "minLength": 1,
+                                "maxLength": 256,
+                                "format": "date",
+                                "pattern": "^.{1,256}$"
                             },
                             "ignoredInternalValue": {
-                                "anyOf": [{
-                                        "type": "null"
-                                    }, {
-                                        "type": "integer",
-                                        "title": "Integer",
-                                        "description": "looked-up from field: Integer",
-                                        "default": 1,
-                                        "enum": [1, 2, 3, 4, 5],
-                                        "minimum": 1,
-                                        "exclusiveMinimum": 0,
-                                        "maximum": 10,
-                                        "exclusiveMaximum": 11,
-                                        "multipleOf": 1
-                                    }]
+                                "type": ["integer", "null"],
+                                "title": "Integer",
+                                "description": "looked-up from field: Integer",
+                                "default": 1,
+                                "enum": [1, 2, 3, 4, 5],
+                                "minimum": 1,
+                                "exclusiveMinimum": 0,
+                                "maximum": 10,
+                                "exclusiveMaximum": 11,
+                                "multipleOf": 1
                             },
                             "primitiveValue": {
                                 "type": ["integer", "null"],
@@ -490,37 +414,29 @@
                     "uniqueItems": false,
                     "type": ["array", "null"],
                     "items": {
-                        "anyOf": [{
-                                "type": "null"
-                            }, {
-                                "type": "integer",
-                                "title": "Long",
-                                "description": "looked-up from field: Long",
-                                "default": 1,
-                                "enum": [1, 2, 3, 4, 5],
-                                "minimum": 1,
-                                "exclusiveMinimum": 0,
-                                "maximum": 10,
-                                "exclusiveMaximum": 11,
-                                "multipleOf": 1
-                            }]
+                        "type": ["integer", "null"],
+                        "title": "Long",
+                        "description": "looked-up from field: Long",
+                        "default": 1,
+                        "enum": [1, 2, 3, 4, 5],
+                        "minimum": 1,
+                        "exclusiveMinimum": 0,
+                        "maximum": 10,
+                        "exclusiveMaximum": 11,
+                        "multipleOf": 1
                     }
                 },
                 "genericValue": {
-                    "anyOf": [{
-                            "type": "null"
-                        }, {
-                            "type": "integer",
-                            "title": "Long",
-                            "description": "looked-up from field: Long",
-                            "default": 1,
-                            "enum": [1, 2, 3, 4, 5],
-                            "minimum": 1,
-                            "exclusiveMinimum": 0,
-                            "maximum": 10,
-                            "exclusiveMaximum": 11,
-                            "multipleOf": 1
-                        }]
+                    "type": ["integer", "null"],
+                    "title": "Long",
+                    "description": "looked-up from field: Long",
+                    "default": 1,
+                    "enum": [1, 2, 3, 4, 5],
+                    "minimum": 1,
+                    "exclusiveMinimum": 0,
+                    "maximum": 10,
+                    "exclusiveMaximum": 11,
+                    "multipleOf": 1
                 }
             },
             "title": "TestClass2<Long>",
@@ -550,37 +466,29 @@
                         "uniqueItems": false,
                         "type": ["array", "null"],
                         "items": {
-                            "anyOf": [{
-                                    "type": "null"
-                                }, {
-                                    "type": "integer",
-                                    "title": "Long",
-                                    "description": "looked-up from field: Long",
-                                    "default": 1,
-                                    "enum": [1, 2, 3, 4, 5],
-                                    "minimum": 1,
-                                    "exclusiveMinimum": 0,
-                                    "maximum": 10,
-                                    "exclusiveMaximum": 11,
-                                    "multipleOf": 1
-                                }]
+                            "type": ["integer", "null"],
+                            "title": "Long",
+                            "description": "looked-up from field: Long",
+                            "default": 1,
+                            "enum": [1, 2, 3, 4, 5],
+                            "minimum": 1,
+                            "exclusiveMinimum": 0,
+                            "maximum": 10,
+                            "exclusiveMaximum": 11,
+                            "multipleOf": 1
                         }
                     },
                     "genericValue": {
-                        "anyOf": [{
-                                "type": "null"
-                            }, {
-                                "type": "integer",
-                                "title": "Long",
-                                "description": "looked-up from field: Long",
-                                "default": 1,
-                                "enum": [1, 2, 3, 4, 5],
-                                "minimum": 1,
-                                "exclusiveMinimum": 0,
-                                "maximum": 10,
-                                "exclusiveMaximum": 11,
-                                "multipleOf": 1
-                            }]
+                        "type": ["integer", "null"],
+                        "title": "Long",
+                        "description": "looked-up from field: Long",
+                        "default": 1,
+                        "enum": [1, 2, 3, 4, 5],
+                        "minimum": 1,
+                        "exclusiveMinimum": 0,
+                        "maximum": 10,
+                        "exclusiveMaximum": 11,
+                        "multipleOf": 1
                     }
                 },
                 "title": "TestClass2<Long>",
diff --git a/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionSimpleIntegrationTest.java b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionSimpleIntegrationTest.java
new file mode 100644
index 0000000..212eb98
--- /dev/null
+++ b/jsonschema-module-jackson/src/test/java/com/github/victools/jsonschema/module/jackson/SubtypeResolutionSimpleIntegrationTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2022 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.module.jackson;
+
+import com.fasterxml.jackson.annotation.JsonPropertyDescription;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.github.victools.jsonschema.generator.Option;
+import com.github.victools.jsonschema.generator.OptionPreset;
+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.networknt.schema.JsonSchema;
+import com.networknt.schema.JsonSchemaFactory;
+import com.networknt.schema.SpecVersion;
+import com.networknt.schema.ValidationMessage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.skyscreamer.jsonassert.JSONCompareMode;
+
+/**
+ * Integration test of this module being used in a real SchemaGenerator instance, focusing on the subtype resolution.
+ */
+public class SubtypeResolutionSimpleIntegrationTest {
+
+    @Test
+    public void testIntegration() throws Exception {
+        SchemaGeneratorConfig config = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2019_09, OptionPreset.PLAIN_JSON)
+                .with(Option.DEFINITIONS_FOR_MEMBER_SUPERTYPES)
+                .with(new JacksonModule())
+                .build();
+        SchemaGenerator generator = new SchemaGenerator(config);
+        JsonNode result = generator.generateSchema(TestClassForSubtypeResolution.class);
+
+        String rawJsonSchema = result.toString();
+        JSONAssert.assertEquals('\n' + rawJsonSchema + '\n',
+                loadResource("subtype-simple-integration-test-result.json"), rawJsonSchema, JSONCompareMode.STRICT);
+
+        JsonSchema schemaForValidation = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909).getSchema(result);
+        String jsonInstance = config.getObjectMapper().writeValueAsString(new TestClassForSubtypeResolution());
+
+        Set<ValidationMessage> validationResult = schemaForValidation.validate(config.getObjectMapper().readTree(jsonInstance));
+        if (!validationResult.isEmpty()) {
+            Assertions.fail("\n" + jsonInstance + "\n  " + validationResult.stream()
+                    .map(ValidationMessage::getMessage)
+                    .collect(Collectors.joining("\n  ")));
+        }
+    }
+
+    private static String loadResource(String resourcePath) throws IOException {
+        StringBuilder stringBuilder = new StringBuilder();
+        try (InputStream inputStream = SubtypeResolutionSimpleIntegrationTest.class
+                .getResourceAsStream(resourcePath);
+                Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) {
+            while (scanner.hasNext()) {
+                stringBuilder.append(scanner.nextLine()).append('\n');
+            }
+        }
+        String fileAsString = stringBuilder.toString();
+        return fileAsString;
+    }
+
+    private static class TestClassForSubtypeResolution {
+
+        @JsonPropertyDescription("A member description")
+        public TestSuperClass supertypeA;
+        public TestSuperClass supertypeB;
+
+        TestClassForSubtypeResolution() {
+            this.supertypeA = new TestSubClassA();
+            this.supertypeB = new TestSubClassB();
+        }
+    }
+
+    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
+    @JsonSubTypes({
+        @JsonSubTypes.Type(value = TestSubClassA.class, name = "SubClassA"),
+        @JsonSubTypes.Type(value = TestSubClassB.class, name = "SubClassB")
+    })
+    private static class TestSuperClass {
+
+    }
+
+    private static class TestSubClassA extends TestSuperClass {
+
+        public String aProperty;
+
+        public TestSubClassA() {
+            this.aProperty = "a";
+        }
+    }
+
+    private static class TestSubClassB extends TestSuperClass {
+
+        public int bProperty;
+
+        TestSubClassB() {
+            this.bProperty = 'b';
+        }
+    }
+}
diff --git a/jsonschema-module-jackson/src/test/resources/com/github/victools/jsonschema/module/jackson/subtype-simple-integration-test-result.json b/jsonschema-module-jackson/src/test/resources/com/github/victools/jsonschema/module/jackson/subtype-simple-integration-test-result.json
new file mode 100644
index 0000000..099ba4d
--- /dev/null
+++ b/jsonschema-module-jackson/src/test/resources/com/github/victools/jsonschema/module/jackson/subtype-simple-integration-test-result.json
@@ -0,0 +1,52 @@
+{
+    "$schema": "https://json-schema.org/draft/2019-09/schema",
+    "$defs": {
+        "TestSuperClass": {
+            "anyOf": [{
+                    "allOf": [{
+                            "type": "object",
+                            "properties": {
+                                "aProperty": {
+                                    "type": "string"
+                                }
+                            }
+                        }, {
+                            "type": "object",
+                            "properties": {
+                                "@type": {
+                                    "const": "SubClassA"
+                                }
+                            },
+                            "required": ["@type"]
+                        }]
+                }, {
+                    "allOf": [{
+                            "type": "object",
+                            "properties": {
+                                "bProperty": {
+                                    "type": "integer"
+                                }
+                            }
+                        }, {
+                            "type": "object",
+                            "properties": {
+                                "@type": {
+                                    "const": "SubClassB"
+                                }
+                            },
+                            "required": ["@type"]
+                        }]
+                }]
+        }
+    },
+    "type": "object",
+    "properties": {
+        "supertypeA": {
+            "$ref": "#/$defs/TestSuperClass",
+            "description": "A member description"
+        },
+        "supertypeB": {
+            "$ref": "#/$defs/TestSuperClass"
+        }
+    }
+}
diff --git a/jsonschema-module-swagger-1.5/src/test/resources/com/github/victools/jsonschema/module/swagger15/integration-test-result.json b/jsonschema-module-swagger-1.5/src/test/resources/com/github/victools/jsonschema/module/swagger15/integration-test-result.json
index fef6081..90f03d4 100644
--- a/jsonschema-module-swagger-1.5/src/test/resources/com/github/victools/jsonschema/module/swagger15/integration-test-result.json
+++ b/jsonschema-module-swagger-1.5/src/test/resources/com/github/victools/jsonschema/module/swagger15/integration-test-result.json
@@ -2,13 +2,9 @@
     "type": "object",
     "properties": {
         "fieldWithDescriptionAndAllowableValues": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "type": "string",
-                    "description": "field description",
-                    "enum": ["A", "B", "C", "D"]
-                }]
+            "type": ["string", "null"],
+            "description": "field description",
+            "enum": ["A", "B", "C", "D"]
         },
         "fieldWithExclusiveNumericRange": {
             "type": "integer",
diff --git a/jsonschema-module-swagger-2/src/test/resources/com/github/victools/jsonschema/module/swagger2/integration-test-result-TestClass.json b/jsonschema-module-swagger-2/src/test/resources/com/github/victools/jsonschema/module/swagger2/integration-test-result-TestClass.json
index a8a5f6f..07f34a6 100644
--- a/jsonschema-module-swagger-2/src/test/resources/com/github/victools/jsonschema/module/swagger2/integration-test-result-TestClass.json
+++ b/jsonschema-module-swagger-2/src/test/resources/com/github/victools/jsonschema/module/swagger2/integration-test-result-TestClass.json
@@ -3,15 +3,11 @@
     "type": "object",
     "properties": {
         "fieldWithDescriptionAndAllowableValues": {
-            "anyOf": [{
-                    "type": "null"
-                }, {
-                    "type": "string",
-                    "description": "field description",
-                    "enum": ["A", "B", "C", "D"],
-                    "minLength": 1,
-                    "maxLength": 1
-                }]
+            "type": ["string", "null"],
+            "description": "field description",
+            "enum": ["A", "B", "C", "D"],
+            "minLength": 1,
+            "maxLength": 1
         },
         "fieldWithExclusiveNumericRange": {
             "type": "integer",