Repository: victools/jsonschema-generator
Pull request #388 (2023-10-24 02:57:56)

feat: add `withObjectMapper` method to customize serialization of schemas to file
Hi, I put together this rough PR based on our discussion in #384. 

3 quick questions on this:
1. Assuming the logic looks fine to you, can you clarify which test classes I need to update? (So far I found `SchemaGeneratorConfigBuilderTest.java`).
2. Do I need to update the github.io documentation you have published on the gh-pages branch?
3. Is it worthwhile to add an example within jsonschema-examples demonstrating the customization of the ObjectMapper to print yaml?

takanuva15: > To answer your questions:
> ...

Thanks for the reply. I've updated the PR and left the documentation untouched. 

This change is really only relevant to the maven plugin, because if a dev is manually making their own schema through the builder, then they'll have access to the root JsonNode and can serialize it however they want. 

In that sense, perhaps the documentation would make more sense to go under `_maven-plugin.md`. In any case, I'll leave it to you to configure it as you like.

Patch:
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGenerator.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGenerator.java
index 34dff07..b02d432 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGenerator.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGenerator.java
@@ -75,4 +75,13 @@ public class SchemaGenerator {
     public SchemaBuilder buildMultipleSchemaDefinitions() {
         return SchemaBuilder.forMultipleTypes(this.config, this.typeContext);
     }
+
+    /**
+     * Returns the {@link SchemaGeneratorConfig} associated with this {@link SchemaGenerator}.
+     *
+     * @return a {@link SchemaGeneratorConfig} instance
+     */
+    public SchemaGeneratorConfig getConfig() {
+        return this.config;
+    }
 }
diff --git a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigBuilder.java b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigBuilder.java
index 90e5610..07a7d15 100644
--- a/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigBuilder.java
+++ b/jsonschema-generator/src/main/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigBuilder.java
@@ -19,6 +19,7 @@ package com.github.victools.jsonschema.generator;
 import com.fasterxml.classmate.AnnotationInclusion;
 import com.fasterxml.jackson.core.json.JsonWriteFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.github.victools.jsonschema.generator.impl.SchemaGeneratorConfigImpl;
 import java.lang.annotation.Annotation;
@@ -41,7 +42,9 @@ public class SchemaGeneratorConfigBuilder {
      * @return default ObjectMapper instance
      */
     private static ObjectMapper createDefaultObjectMapper() {
-        ObjectMapper mapper = new ObjectMapper();
+        ObjectMapper mapper = new ObjectMapper()
+                // since version 4.32.0; pretty print by default (can be overridden by supplying explicit mapper)
+                .enable(SerializationFeature.INDENT_OUTPUT);
         mapper.getSerializationConfig()
                 // since version 4.21.0
                 .with(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS);
@@ -51,7 +54,7 @@ public class SchemaGeneratorConfigBuilder {
         return mapper;
     }
 
-    private final ObjectMapper objectMapper;
+    private ObjectMapper objectMapper;
     private final OptionPreset preset;
     private final SchemaVersion schemaVersion;
 
@@ -306,4 +309,19 @@ public class SchemaGeneratorConfigBuilder {
         this.annotationInclusionOverrides.put(annotationType, override);
         return this;
     }
+
+    /**
+     * Register a custom {@link ObjectMapper} to create object and array nodes for the JSON structure being
+     * generated. Additionally, it is used to serialize a given schema, e.g., within the standard Maven plugin as
+     * either YAML or JSON.
+     *
+     * @param objectMapper supplier for object and array nodes for the JSON structure being generated
+     * @return this builder instance (for chaining)
+     *
+     * @since 4.32.0
+     */
+    public SchemaGeneratorConfigBuilder withObjectMapper(ObjectMapper objectMapper) {
+        this.objectMapper = objectMapper;
+        return this;
+    }
 }
diff --git a/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojo.java b/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojo.java
index 897cd30..d136ab2 100644
--- a/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojo.java
+++ b/jsonschema-maven-plugin/src/main/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojo.java
@@ -17,6 +17,7 @@
 package com.github.victools.jsonschema.plugin.maven;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.github.victools.jsonschema.generator.Module;
 import com.github.victools.jsonschema.generator.Option;
 import com.github.victools.jsonschema.generator.OptionPreset;
@@ -626,9 +627,10 @@ public class SchemaGeneratorMojo extends AbstractMojo {
      * @throws MojoExecutionException In case of problems when writing the targeted file
      */
     private void writeToFile(JsonNode jsonSchema, File file) throws MojoExecutionException {
+        ObjectMapper mapper = getGenerator().getConfig().getObjectMapper();
         try (FileOutputStream outputStream = new FileOutputStream(file);
                 PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) {
-            writer.print(jsonSchema.toPrettyString());
+            writer.print(mapper.writeValueAsString(jsonSchema));
         } catch (IOException e) {
             throw new MojoExecutionException("Error: Can not write to file " + file, e);
         }


Test patch:
diff --git a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigBuilderTest.java b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigBuilderTest.java
index 46d8744..73f45f2 100644
--- a/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigBuilderTest.java
+++ b/jsonschema-generator/src/test/java/com/github/victools/jsonschema/generator/SchemaGeneratorConfigBuilderTest.java
@@ -16,6 +16,7 @@
 
 package com.github.victools.jsonschema.generator;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -49,6 +50,15 @@ public class SchemaGeneratorConfigBuilderTest {
         Assertions.assertFalse(this.builder.getSetting(Option.DEFINITIONS_FOR_ALL_OBJECTS));
     }
 
+    @Test
+    public void testWithObjectMapper() {
+        ObjectMapper currMapper = this.builder.getObjectMapper();
+        ObjectMapper newMapper = new ObjectMapper();
+        this.builder.withObjectMapper(newMapper);
+        Assertions.assertSame(newMapper, this.builder.getObjectMapper());
+        Assertions.assertNotEquals(currMapper, this.builder.getObjectMapper());
+    }
+
     @Test
     public void testForFields() {
         Assertions.assertNotNull(this.builder.forFields());
diff --git a/jsonschema-maven-plugin/src/test/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojoTest.java b/jsonschema-maven-plugin/src/test/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojoTest.java
index 1b3dffc..9390041 100644
--- a/jsonschema-maven-plugin/src/test/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojoTest.java
+++ b/jsonschema-maven-plugin/src/test/java/com/github/victools/jsonschema/plugin/maven/SchemaGeneratorMojoTest.java
@@ -75,7 +75,12 @@ public class SchemaGeneratorMojoTest extends AbstractMojoTestCase {
         File referenceFile = new File(testCaseLocation, testCaseName + "-reference.json");
         Assertions.assertTrue(referenceFile.exists());
         Assertions.assertTrue(FileUtils.contentEqualsIgnoreEOL(resultFile, referenceFile, CHARSET_NAME),
-                "Generated schema for " + testCaseName + " is not equal to the expected reference.");
+                "Generated schema for " + testCaseName + " is not equal to the expected reference.\n"
+                        + "Generated:\n"
+                        + FileUtils.readFileToString(resultFile)
+                        + "\n----------\n"
+                        + "Expected:\n"
+                        + FileUtils.readFileToString(referenceFile));
     }
 
     /**