Loading README.md +19 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ Current version: *1.0.10* * Works well with Generated GUI's using [https://github.com/jdorn/json-editor](https://github.com/jdorn/json-editor) - (Must be configured to use this mode) - Special handling of Option-/Optional-properties using oneOf. * Supports custom Class-to-format-Mapping **Benefits** Loading Loading @@ -86,6 +88,18 @@ This is how to generate jsonSchema used for generating HTML5 GUI using [json-edi val jsonSchemaAsString:String = objectMapper.writeValueAsString(jsonSchema) ``` This is how to generate jsonSchema using custom type-to-format-mapping using Scala: ```scala val objectMapper = new ObjectMapper val config:JsonSchemaConfig = JsonSchemaConfig.vanillaJsonSchemaDraft4.copy( customType2FormatMapping = Map( "java.time.OffsetDateTime" -> "date-time-ABC-Special" ) ) val jsonSchemaGenerator = new JsonSchemaGenerator(objectMapper, config = config) val jsonSchema:JsonNode = jsonSchemaGenerator.generateJsonSchema(classOf[YourPOJO]) val jsonSchemaAsString:String = objectMapper.writeValueAsString(jsonSchema) ``` **Note about Scala and Option[Int]**: Loading Loading @@ -116,6 +130,11 @@ Code - Using Java // If using JsonSchema to generate HTML5 GUI: // JsonSchemaGenerator html5 = new JsonSchemaGenerator(objectMapper, JsonSchemaConfig.html5EnabledSchema() ); // If you want to confioure it manually: // JsonSchemaConfig config = JsonSchemaConfig.create(...); // JsonSchemaGenerator generator = new JsonSchemaGenerator(objectMapper, config); JsonNode jsonSchema = jsonSchemaGenerator.generateJsonSchema(YourPOJO.class); String jsonSchemaAsString = objectMapper.writeValueAsString(jsonSchema); Loading project/build.properties 0 → 100644 +1 −0 Original line number Diff line number Diff line sbt.version=0.13.13 No newline at end of file src/main/scala/com/kjetland/jackson/jsonSchema/JsonSchemaGenerator.scala +55 −11 Original line number Diff line number Diff line Loading @@ -30,9 +30,9 @@ object JsonSchemaConfig { usePropertyOrdering = false, hidePolymorphismTypeProperty = false, disableWarnings = false, useImprovedDateFormatMapping = false, useMinLengthForNotNull = false, useTypeIdForDefinitionName = false useTypeIdForDefinitionName = false, customType2FormatMapping = Map() ) /** Loading @@ -49,10 +49,46 @@ object JsonSchemaConfig { usePropertyOrdering = true, hidePolymorphismTypeProperty = true, disableWarnings = false, useImprovedDateFormatMapping = true, useMinLengthForNotNull = true, useTypeIdForDefinitionName = false useTypeIdForDefinitionName = false, customType2FormatMapping = Map[String,String]( // Java7 dates "java.time.LocalDateTime" -> "datetime-local", "java.time.OffsetDateTime" -> "datetime", "java.time.LocalDate" -> "date", // Joda-dates "org.joda.time.LocalDate" -> "date" ) ) // Java-API def create( autoGenerateTitleForProperties:Boolean, defaultArrayFormat:Optional[String], useOneOfForOption:Boolean, usePropertyOrdering:Boolean, hidePolymorphismTypeProperty:Boolean, disableWarnings:Boolean, useMinLengthForNotNull:Boolean, useTypeIdForDefinitionName:Boolean, customType2FormatMapping:java.util.Map[String, String] ):JsonSchemaConfig = { import scala.collection.JavaConverters._ JsonSchemaConfig( autoGenerateTitleForProperties, Option(defaultArrayFormat.orElse(null)), useOneOfForOption, usePropertyOrdering, hidePolymorphismTypeProperty, disableWarnings, useMinLengthForNotNull, useTypeIdForDefinitionName, customType2FormatMapping.asScala.toMap ) } } Loading @@ -64,9 +100,9 @@ case class JsonSchemaConfig usePropertyOrdering:Boolean, hidePolymorphismTypeProperty:Boolean, disableWarnings:Boolean, useImprovedDateFormatMapping:Boolean, useMinLengthForNotNull:Boolean, useTypeIdForDefinitionName:Boolean useTypeIdForDefinitionName:Boolean, customType2FormatMapping:Map[String, String] ) Loading Loading @@ -520,7 +556,7 @@ class JsonSchemaGenerator // If class is annotated with JsonSchemaFormat, we should add it val ac = AnnotatedClass.construct(_type, objectMapper.getDeserializationConfig()) Option(ac.getAnnotations.get(classOf[JsonSchemaFormat])).map(_.value()).foreach { resolvePropertyFormat(_type, objectMapper).foreach { format => setFormat(thisObjectNode, format) } Loading Loading @@ -756,15 +792,23 @@ class JsonSchemaGenerator s.substring(0,1).toUpperCase() + s.substring(1) } def resolvePropertyFormat(_type: JavaType, objectMapper:ObjectMapper):Option[String] = { val ac = AnnotatedClass.construct(_type, objectMapper.getDeserializationConfig()) resolvePropertyFormat(Option(ac.getAnnotation(classOf[JsonSchemaFormat])), _type.getRawClass.getName) } def resolvePropertyFormat(prop: BeanProperty):Option[String] = { // Prefer format specified in annotation Option(prop.getAnnotation(classOf[JsonSchemaFormat])).map { resolvePropertyFormat(Option(prop.getAnnotation(classOf[JsonSchemaFormat])), prop.getType.getRawClass.getName) } def resolvePropertyFormat(jsonSchemaFormatAnnotation:Option[JsonSchemaFormat], rawClassName:String):Option[String] = { // Prefer format specified in annotation jsonSchemaFormatAnnotation.map { jsonSchemaFormat => jsonSchemaFormat.value() }.orElse { if( config.useImprovedDateFormatMapping ) { dateFormatMapping.get(prop.getType.getRawClass.getName) } else None config.customType2FormatMapping.get(rawClassName) } } Loading src/test/java/com/kjetland/jackson/jsonSchema/UseItFromJavaTest.java +12 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import scala.None; import scala.Option; import java.time.OffsetDateTime; import java.util.HashMap; import java.util.Map; import java.util.Optional; public class UseItFromJavaTest { static class MyJavaPojo { Loading @@ -17,6 +22,13 @@ public class UseItFromJavaTest { // TODO - This is not very beautiful from Java - Need to improve Java API g1.generateJsonSchema(MyJavaPojo.class); g1.generateJsonSchema(MyJavaPojo.class, "My title", "My description"); // Create custom JsonSchemaConfig from java Map<String,String> customMapping = new HashMap<>(); customMapping.put(OffsetDateTime.class.getName(), "date-time"); JsonSchemaConfig config = JsonSchemaConfig.create( true, Optional.of("A"), true, true, true, true, true, true, customMapping); JsonSchemaGenerator g2 = new JsonSchemaGenerator(objectMapper, config); } } src/test/scala/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorTest.scala +1 −11 Original line number Diff line number Diff line Loading @@ -55,17 +55,7 @@ class JsonSchemaGeneratorTest extends FunSuite with Matchers { val jsonSchemaGeneratorScala = new JsonSchemaGenerator(_objectMapperScala, debug = true) val jsonSchemaGeneratorScalaHTML5 = new JsonSchemaGenerator(_objectMapperScala, debug = true, config = JsonSchemaConfig.html5EnabledSchema) val vanillaJsonSchemaDraft4WithIds = JsonSchemaConfig( autoGenerateTitleForProperties = true, defaultArrayFormat = Some("table"), useOneOfForOption = true, usePropertyOrdering = true, hidePolymorphismTypeProperty = true, disableWarnings = false, useImprovedDateFormatMapping = true, useMinLengthForNotNull = true, useTypeIdForDefinitionName = true ) val vanillaJsonSchemaDraft4WithIds = JsonSchemaConfig.html5EnabledSchema.copy(useTypeIdForDefinitionName = true) val jsonSchemaGeneratorWithIds = new JsonSchemaGenerator(_objectMapperScala, debug = true, vanillaJsonSchemaDraft4WithIds) val testData = new TestData{} Loading Loading
README.md +19 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ Current version: *1.0.10* * Works well with Generated GUI's using [https://github.com/jdorn/json-editor](https://github.com/jdorn/json-editor) - (Must be configured to use this mode) - Special handling of Option-/Optional-properties using oneOf. * Supports custom Class-to-format-Mapping **Benefits** Loading Loading @@ -86,6 +88,18 @@ This is how to generate jsonSchema used for generating HTML5 GUI using [json-edi val jsonSchemaAsString:String = objectMapper.writeValueAsString(jsonSchema) ``` This is how to generate jsonSchema using custom type-to-format-mapping using Scala: ```scala val objectMapper = new ObjectMapper val config:JsonSchemaConfig = JsonSchemaConfig.vanillaJsonSchemaDraft4.copy( customType2FormatMapping = Map( "java.time.OffsetDateTime" -> "date-time-ABC-Special" ) ) val jsonSchemaGenerator = new JsonSchemaGenerator(objectMapper, config = config) val jsonSchema:JsonNode = jsonSchemaGenerator.generateJsonSchema(classOf[YourPOJO]) val jsonSchemaAsString:String = objectMapper.writeValueAsString(jsonSchema) ``` **Note about Scala and Option[Int]**: Loading Loading @@ -116,6 +130,11 @@ Code - Using Java // If using JsonSchema to generate HTML5 GUI: // JsonSchemaGenerator html5 = new JsonSchemaGenerator(objectMapper, JsonSchemaConfig.html5EnabledSchema() ); // If you want to confioure it manually: // JsonSchemaConfig config = JsonSchemaConfig.create(...); // JsonSchemaGenerator generator = new JsonSchemaGenerator(objectMapper, config); JsonNode jsonSchema = jsonSchemaGenerator.generateJsonSchema(YourPOJO.class); String jsonSchemaAsString = objectMapper.writeValueAsString(jsonSchema); Loading
project/build.properties 0 → 100644 +1 −0 Original line number Diff line number Diff line sbt.version=0.13.13 No newline at end of file
src/main/scala/com/kjetland/jackson/jsonSchema/JsonSchemaGenerator.scala +55 −11 Original line number Diff line number Diff line Loading @@ -30,9 +30,9 @@ object JsonSchemaConfig { usePropertyOrdering = false, hidePolymorphismTypeProperty = false, disableWarnings = false, useImprovedDateFormatMapping = false, useMinLengthForNotNull = false, useTypeIdForDefinitionName = false useTypeIdForDefinitionName = false, customType2FormatMapping = Map() ) /** Loading @@ -49,10 +49,46 @@ object JsonSchemaConfig { usePropertyOrdering = true, hidePolymorphismTypeProperty = true, disableWarnings = false, useImprovedDateFormatMapping = true, useMinLengthForNotNull = true, useTypeIdForDefinitionName = false useTypeIdForDefinitionName = false, customType2FormatMapping = Map[String,String]( // Java7 dates "java.time.LocalDateTime" -> "datetime-local", "java.time.OffsetDateTime" -> "datetime", "java.time.LocalDate" -> "date", // Joda-dates "org.joda.time.LocalDate" -> "date" ) ) // Java-API def create( autoGenerateTitleForProperties:Boolean, defaultArrayFormat:Optional[String], useOneOfForOption:Boolean, usePropertyOrdering:Boolean, hidePolymorphismTypeProperty:Boolean, disableWarnings:Boolean, useMinLengthForNotNull:Boolean, useTypeIdForDefinitionName:Boolean, customType2FormatMapping:java.util.Map[String, String] ):JsonSchemaConfig = { import scala.collection.JavaConverters._ JsonSchemaConfig( autoGenerateTitleForProperties, Option(defaultArrayFormat.orElse(null)), useOneOfForOption, usePropertyOrdering, hidePolymorphismTypeProperty, disableWarnings, useMinLengthForNotNull, useTypeIdForDefinitionName, customType2FormatMapping.asScala.toMap ) } } Loading @@ -64,9 +100,9 @@ case class JsonSchemaConfig usePropertyOrdering:Boolean, hidePolymorphismTypeProperty:Boolean, disableWarnings:Boolean, useImprovedDateFormatMapping:Boolean, useMinLengthForNotNull:Boolean, useTypeIdForDefinitionName:Boolean useTypeIdForDefinitionName:Boolean, customType2FormatMapping:Map[String, String] ) Loading Loading @@ -520,7 +556,7 @@ class JsonSchemaGenerator // If class is annotated with JsonSchemaFormat, we should add it val ac = AnnotatedClass.construct(_type, objectMapper.getDeserializationConfig()) Option(ac.getAnnotations.get(classOf[JsonSchemaFormat])).map(_.value()).foreach { resolvePropertyFormat(_type, objectMapper).foreach { format => setFormat(thisObjectNode, format) } Loading Loading @@ -756,15 +792,23 @@ class JsonSchemaGenerator s.substring(0,1).toUpperCase() + s.substring(1) } def resolvePropertyFormat(_type: JavaType, objectMapper:ObjectMapper):Option[String] = { val ac = AnnotatedClass.construct(_type, objectMapper.getDeserializationConfig()) resolvePropertyFormat(Option(ac.getAnnotation(classOf[JsonSchemaFormat])), _type.getRawClass.getName) } def resolvePropertyFormat(prop: BeanProperty):Option[String] = { // Prefer format specified in annotation Option(prop.getAnnotation(classOf[JsonSchemaFormat])).map { resolvePropertyFormat(Option(prop.getAnnotation(classOf[JsonSchemaFormat])), prop.getType.getRawClass.getName) } def resolvePropertyFormat(jsonSchemaFormatAnnotation:Option[JsonSchemaFormat], rawClassName:String):Option[String] = { // Prefer format specified in annotation jsonSchemaFormatAnnotation.map { jsonSchemaFormat => jsonSchemaFormat.value() }.orElse { if( config.useImprovedDateFormatMapping ) { dateFormatMapping.get(prop.getType.getRawClass.getName) } else None config.customType2FormatMapping.get(rawClassName) } } Loading
src/test/java/com/kjetland/jackson/jsonSchema/UseItFromJavaTest.java +12 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import scala.None; import scala.Option; import java.time.OffsetDateTime; import java.util.HashMap; import java.util.Map; import java.util.Optional; public class UseItFromJavaTest { static class MyJavaPojo { Loading @@ -17,6 +22,13 @@ public class UseItFromJavaTest { // TODO - This is not very beautiful from Java - Need to improve Java API g1.generateJsonSchema(MyJavaPojo.class); g1.generateJsonSchema(MyJavaPojo.class, "My title", "My description"); // Create custom JsonSchemaConfig from java Map<String,String> customMapping = new HashMap<>(); customMapping.put(OffsetDateTime.class.getName(), "date-time"); JsonSchemaConfig config = JsonSchemaConfig.create( true, Optional.of("A"), true, true, true, true, true, true, customMapping); JsonSchemaGenerator g2 = new JsonSchemaGenerator(objectMapper, config); } }
src/test/scala/com/kjetland/jackson/jsonSchema/JsonSchemaGeneratorTest.scala +1 −11 Original line number Diff line number Diff line Loading @@ -55,17 +55,7 @@ class JsonSchemaGeneratorTest extends FunSuite with Matchers { val jsonSchemaGeneratorScala = new JsonSchemaGenerator(_objectMapperScala, debug = true) val jsonSchemaGeneratorScalaHTML5 = new JsonSchemaGenerator(_objectMapperScala, debug = true, config = JsonSchemaConfig.html5EnabledSchema) val vanillaJsonSchemaDraft4WithIds = JsonSchemaConfig( autoGenerateTitleForProperties = true, defaultArrayFormat = Some("table"), useOneOfForOption = true, usePropertyOrdering = true, hidePolymorphismTypeProperty = true, disableWarnings = false, useImprovedDateFormatMapping = true, useMinLengthForNotNull = true, useTypeIdForDefinitionName = true ) val vanillaJsonSchemaDraft4WithIds = JsonSchemaConfig.html5EnabledSchema.copy(useTypeIdForDefinitionName = true) val jsonSchemaGeneratorWithIds = new JsonSchemaGenerator(_objectMapperScala, debug = true, vanillaJsonSchemaDraft4WithIds) val testData = new TestData{} Loading