diff --git a/CHANGELOG.md b/CHANGELOG.md
index e8930f1..1ded7bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,8 +2,9 @@
The format is based on [Keep a Changelog](http://keepachangelog.com/).
-## Unreleased
+## [0.109] - 2024-09-05
### Changed
+- templates: fixed bug in templates for map-based classes
- `CodeGenerator`: added explicit types to public APIs
## [0.108] - 2024-08-07
diff --git a/README.md b/README.md
index d703a95..3d04aa0 100644
--- a/README.md
+++ b/README.md
@@ -334,25 +334,25 @@ operation:
## Dependency Specification
-The latest version of the library is 0.108, and it may be obtained from the Maven Central repository.
+The latest version of the library is 0.109, and it may be obtained from the Maven Central repository.
### Maven
```xml
net.pwall.json
json-kotlin-schema-codegen
- 0.108
+ 0.109
```
### Gradle
```groovy
- implementation 'net.pwall.json:json-kotlin-schema-codegen:0.108'
+ implementation 'net.pwall.json:json-kotlin-schema-codegen:0.109'
```
### Gradle (kts)
```kotlin
- implementation("net.pwall.json:json-kotlin-schema-codegen:0.108")
+ implementation("net.pwall.json:json-kotlin-schema-codegen:0.109")
```
Peter Wall
-2024-08-07
+2024-09-05
diff --git a/pom.xml b/pom.xml
index 02dc74e..28951e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
net.pwall.json
json-kotlin-schema-codegen
- 0.108
+ 0.109
JSON Schema Code Generation
Code generation from JSON Schema to Kotlin or Java
jar
diff --git a/src/main/resources/kotlin/class_map_property.mustache b/src/main/resources/kotlin/class_map_property.mustache
index 880e7c2..f387b3d 100644
--- a/src/main/resources/kotlin/class_map_property.mustache
+++ b/src/main/resources/kotlin/class_map_property.mustache
@@ -1,7 +1,6 @@
-{{&indent}} require(cg_map["{{&name}}"] is {{#isArray}}{{>list_or_set}}<*>{{/isArray}}{{!
-}}{{^isArray}}{{>type_ex_nullable}}{{/isArray}}) { "{{&name}} is not the correct type, expecting {{>type}}" }
+{{&indent}} require(cg_map["{{&name}}"] is {{>type_or_list_or_set}}) { "{{&name}} is not the correct type, expecting {{>type}}" }
{{#isArray}}{{&indent}} (cg_map["{{&name}}"] as {{>list_or_set}}<*>).forEach { {{#indent.increment}}{{#arrayItems}}{{&kotlinName}} ->
{{>class_map_property_item}}{{/arrayItems}}{{/indent.increment}}{{&indent}} }
-{{/isArray}}{{^isArray}}{{#validations}}{{#first}}{{&indent}} (cg_map["{{&name}}"] as {{>type_ex_nullable}}).let { {{&kotlinName}} ->
+{{/isArray}}{{^isArray}}{{#validations}}{{#first}}{{&indent}} (cg_map["{{&name}}"] as {{>type}}){{#nullable}}?{{/nullable}}.let { {{&kotlinName}} ->
{{/first}}{{#indent.increment}}{{>validations_2}}{{/indent.increment}}{{#last}}{{&indent}} }
{{/last}}{{/validations}}{{/isArray}}
\ No newline at end of file
diff --git a/src/main/resources/kotlin/nested_class_map.mustache b/src/main/resources/kotlin/nested_class_map.mustache
index 70292e6..d3a1e75 100644
--- a/src/main/resources/kotlin/nested_class_map.mustache
+++ b/src/main/resources/kotlin/nested_class_map.mustache
@@ -6,9 +6,12 @@
{{#properties}}{{#defaultValue}}{{&indent}} if (cg_map.containsKey("{{&name}}")){{#validations}}{{#first}} {{&openBrace}}{{/first}}{{/validations}}
{{#indent.increment}}{{>class_map_property}}{{/indent.increment}}{{#validations}}{{#first}}{{&indent}} }
{{/first}}{{/validations}}{{/defaultValue}}{{^defaultValue}}{{!
-}}{{#nullable}}{{&indent}} if (cg_map.containsKey("{{&name}}")){{#validations}}{{#first}} {{&openBrace}}{{/first}}{{/validations}}
-{{#indent.increment}}{{>class_map_property}}{{/indent.increment}}{{#validations}}{{#first}}{{&indent}} }
-{{/first}}{{/validations}}{{/nullable}}{{^nullable}}{{&indent}} require(cg_map.containsKey("{{&name}}")) { "required property missing - {{&name}}" }
+}}{{#nullable}}{{&indent}} if (cg_map.containsKey("{{&name}}")){{!
+}}{{#isArray}} {{&openBrace}}{{/isArray}}{{^isArray}}{{#validations}}{{#first}} {{&openBrace}}{{/first}}{{/validations}}{{/isArray}}
+{{#indent.increment}}{{>class_map_property}}{{/indent.increment}}{{!
+}}{{#isArray}}{{&indent}} }
+{{/isArray}}{{^isArray}}{{#validations}}{{#first}}{{&indent}} }
+{{/first}}{{/validations}}{{/isArray}}{{/nullable}}{{^nullable}}{{&indent}} require(cg_map.containsKey("{{&name}}")) { "required property missing - {{&name}}" }
{{>class_map_property}}{{/nullable}}{{/defaultValue}}{{/properties}}{{!
}}{{^properties}}{{#additionalProperties}}{{#validations}}{{#first}}{{&indent}} cg_map.entries.forEach { (key, value) ->
{{/first}}{{#indent.increment}}{{#mapEntryContext}}{{>validations_2}}{{/mapEntryContext}}{{/indent.increment}}{{#last}}{{&indent}} }
@@ -16,9 +19,11 @@
{{#properties}}
{{#schema}}{{#description}}{{&indent}} /** {{&safeDescription}} */
{{/description}}{{/schema}}{{&indent}} val {{&kotlinName}}: {{>type}}{{#defaultValue}}
-{{&indent}} get() = if (cg_map.containsKey("{{&name}}")) cg_map["{{&name}}"] as {{>type}} else {{>default_value}}
+{{#isArray}}{{&indent}} @Suppress("unchecked_cast")
+{{/isArray}}{{&indent}} get() = if (cg_map.containsKey("{{&name}}")) cg_map["{{&name}}"] as {{>type}} else {{>default_value}}
{{/defaultValue}}{{^defaultValue}}{{#nullable}}
-{{&indent}} get() = cg_map["{{&name}}"] as {{>type}}
+{{#isArray}}{{&indent}} @Suppress("unchecked_cast")
+{{/isArray}}{{&indent}} get() = cg_map["{{&name}}"] as {{>type}}
{{/nullable}}{{^nullable}} by cg_map
{{/nullable}}{{/defaultValue}}{{/properties}}
{{&indent}} override fun toString(): String = "{{&className}}(${cg_map.entries.joinToString { "${it.key}=${it.value}" }})"
diff --git a/src/main/resources/kotlin/type_or_list_or_set.mustache b/src/main/resources/kotlin/type_or_list_or_set.mustache
new file mode 100644
index 0000000..460954d
--- /dev/null
+++ b/src/main/resources/kotlin/type_or_list_or_set.mustache
@@ -0,0 +1 @@
+{{#isArray}}{{>list_or_set}}<*>{{/isArray}}{{^isArray}}{{>type}}{{/isArray}}
\ No newline at end of file
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/CodeGeneratorAdditionalPropertiesTest.kt b/src/test/kotlin/net/pwall/json/schema/codegen/CodeGeneratorAdditionalPropertiesTest.kt
index 5a960e9..ca19e95 100644
--- a/src/test/kotlin/net/pwall/json/schema/codegen/CodeGeneratorAdditionalPropertiesTest.kt
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/CodeGeneratorAdditionalPropertiesTest.kt
@@ -123,6 +123,42 @@ class CodeGeneratorAdditionalPropertiesTest {
expect(resultFile("TestApTrueExtra")) { outputDetails.output() }
}
+ @Test fun `should generate code for aP true with optional extra`() {
+ val input = File("src/test/resources/test-ap-true-extra-optional.schema.json")
+ val outputDetails = OutputDetails(TargetFileName("TestApTrueExtraOptional", "kt", packageDirs))
+ CodeGenerator().apply {
+ additionalPropertiesOption = CodeGenerator.AdditionalPropertiesOption.STRICT
+ basePackageName = packageName
+ outputResolver = outputCapture(outputDetails)
+ generate(input)
+ }
+ expect(resultFile("TestApTrueExtraOptional")) { outputDetails.output() }
+ }
+
+ @Test fun `should generate code for aP true with extra with validation`() {
+ val input = File("src/test/resources/test-ap-true-extra-valid.schema.json")
+ val outputDetails = OutputDetails(TargetFileName("TestApTrueExtraValid", "kt", packageDirs))
+ CodeGenerator().apply {
+ additionalPropertiesOption = CodeGenerator.AdditionalPropertiesOption.STRICT
+ basePackageName = packageName
+ outputResolver = outputCapture(outputDetails)
+ generate(input)
+ }
+ expect(resultFile("TestApTrueExtraValid")) { outputDetails.output() }
+ }
+
+ @Test fun `should generate code for aP true with optional extra with validation`() {
+ val input = File("src/test/resources/test-ap-true-extra-opt-valid.schema.json")
+ val outputDetails = OutputDetails(TargetFileName("TestApTrueExtraOptValid", "kt", packageDirs))
+ CodeGenerator().apply {
+ additionalPropertiesOption = CodeGenerator.AdditionalPropertiesOption.STRICT
+ basePackageName = packageName
+ outputResolver = outputCapture(outputDetails)
+ generate(input)
+ }
+ expect(resultFile("TestApTrueExtraOptValid")) { outputDetails.output() }
+ }
+
@Test fun `should generate code for aP true with extra array`() {
val input = File("src/test/resources/test-ap-true-extra-array.schema.json")
val outputDetails = OutputDetails(TargetFileName("TestApTrueExtraArray", "kt", packageDirs))
@@ -135,6 +171,30 @@ class CodeGeneratorAdditionalPropertiesTest {
expect(resultFile("TestApTrueExtraArray")) { outputDetails.output() }
}
+ @Test fun `should generate code for aP true with optional extra array`() {
+ val input = File("src/test/resources/test-ap-true-extra-array-opt.schema.json")
+ val outputDetails = OutputDetails(TargetFileName("TestApTrueExtraArrayOpt", "kt", packageDirs))
+ CodeGenerator().apply {
+ additionalPropertiesOption = CodeGenerator.AdditionalPropertiesOption.STRICT
+ basePackageName = packageName
+ outputResolver = outputCapture(outputDetails)
+ generate(input)
+ }
+ expect(resultFile("TestApTrueExtraArrayOpt")) { outputDetails.output() }
+ }
+
+ @Test fun `should generate code for aP true with optional extra array with validation`() {
+ val input = File("src/test/resources/test-ap-true-extra-array-opt-valid.schema.json")
+ val outputDetails = OutputDetails(TargetFileName("TestApTrueExtraArrayOptValid", "kt", packageDirs))
+ CodeGenerator().apply {
+ additionalPropertiesOption = CodeGenerator.AdditionalPropertiesOption.STRICT
+ basePackageName = packageName
+ outputResolver = outputCapture(outputDetails)
+ generate(input)
+ }
+ expect(resultFile("TestApTrueExtraArrayOptValid")) { outputDetails.output() }
+ }
+
@Test fun `should generate code for aP true with extra with default value`() {
val input = File("src/test/resources/test-ap-true-extra-default.schema.json")
val outputDetails = OutputDetails(TargetFileName("TestApTrueExtraDefault", "kt", packageDirs))
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/AdditionalPropertiesDeserializationTest.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/AdditionalPropertiesDeserializationTest.kt
index 18aaa53..ff3c805 100644
--- a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/AdditionalPropertiesDeserializationTest.kt
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/AdditionalPropertiesDeserializationTest.kt
@@ -94,31 +94,31 @@ class AdditionalPropertiesDeserializationTest {
@Test fun `should deserialize TestApTrueExtra`() {
val json1 = """{"extra":"content"}"""
- val result1 = json1.parseJSON()
+ val result1 = json1.parseJSON()
expect("content") { result1.extra }
assertNull(result1["whatever"])
val json2 = """{"extra":"content","anything":"another"}"""
- val result2 = json2.parseJSON()
+ val result2 = json2.parseJSON()
expect("content") { result2.extra }
expect("another") { result2["anything"] }
assertNull(result2["whatever"])
assertFailsWith {
- """{"anything":"another"}""".parseJSON()
+ """{"anything":"another"}""".parseJSON()
}.cause.let {
assertIs(it)
expect("required property missing - extra") { it.message }
}
assertFailsWith {
- """{"extra":123}""".parseJSON()
+ """{"extra":123}""".parseJSON()
}.let {
expect("Can't deserialize 123 as String at /extra") { it.message }
}
assertFailsWith {
- """{"extra":""}""".parseJSON()
+ """{"extra":""}""".parseJSON()
}.cause.let {
assertIs(it)
expect("extra length < minimum 1 - 0") { it.message }
@@ -150,7 +150,7 @@ class AdditionalPropertiesDeserializationTest {
}
assertFailsWith {
- """{"extra":""}""".parseJSON()
+ """{"extra":""}""".parseJSON()
}.cause.let {
assertIs(it)
expect("extra length < minimum 1 - 0") { it.message }
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/AdditionalPropertiesFunctionalityTest.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/AdditionalPropertiesFunctionalityTest.kt
index 2700a74..1aedebd 100644
--- a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/AdditionalPropertiesFunctionalityTest.kt
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/AdditionalPropertiesFunctionalityTest.kt
@@ -27,6 +27,7 @@ package net.pwall.json.schema.codegen.test.kotlin
import kotlin.test.Test
import kotlin.test.assertFailsWith
+import kotlin.test.assertIs
import kotlin.test.assertNull
import kotlin.test.assertTrue
import kotlin.test.expect
@@ -130,9 +131,143 @@ class AdditionalPropertiesFunctionalityTest {
}.let {
expect("extra is not the correct type, expecting String") { it.message }
}
+ }
+
+ @Test fun `should generate functional TestApTrueExtraOptional`() {
+ val testClass1 = TestApTrueExtraOptional(mapOf(
+ "extra" to "content",
+ ))
+ expect("content") { testClass1.extra }
+ assertNull(testClass1["whatever"])
+ expect("TestApTrueExtraOptional(extra=content)") { testClass1.toString() }
+
+ val testClass2 = TestApTrueExtraOptional(mapOf(
+ "extra" to "content",
+ "anything" to "another",
+ ))
+ expect("content") { testClass2.extra }
+ expect("another") { testClass2["anything"] }
+ assertNull(testClass2["whatever"])
+ expect("TestApTrueExtraOptional(extra=content, anything=another)") { testClass2.toString() }
+
+ val testClass3 = TestApTrueExtraOptional(mapOf(
+ "extra" to null,
+ ))
+ assertNull(testClass3.extra)
+ assertNull(testClass3["whatever"])
+ expect("TestApTrueExtraOptional(extra=null)") { testClass3.toString() }
+
+ val testClass4 = TestApTrueExtraOptional(emptyMap())
+ assertNull(testClass4.extra)
+ assertNull(testClass4["whatever"])
+ expect("TestApTrueExtraOptional()") { testClass4.toString() }
+
+ val testClass5 = TestApTrueExtraOptional(mapOf(
+ "anything" to "another",
+ ))
+ assertNull(testClass5.extra)
+ expect("another") { testClass5["anything"] }
+ assertNull(testClass5["whatever"])
+ expect("TestApTrueExtraOptional(anything=another)") { testClass5.toString() }
assertFailsWith {
- TestApTrueExtra(mapOf(
+ TestApTrueExtraOptional(mapOf(
+ "extra" to 123,
+ ))
+ }.let {
+ expect("extra is not the correct type, expecting String?") { it.message }
+ }
+ }
+
+ @Test fun `should generate functional TestApTrueExtraValid`() {
+ val testClass1 = TestApTrueExtraValid(mapOf(
+ "extra" to "content",
+ ))
+ expect("content") { testClass1.extra }
+ assertNull(testClass1["whatever"])
+ expect("TestApTrueExtraValid(extra=content)") { testClass1.toString() }
+
+ val testClass2 = TestApTrueExtraValid(mapOf(
+ "extra" to "content",
+ "anything" to "another",
+ ))
+ expect("content") { testClass2.extra }
+ expect("another") { testClass2["anything"] }
+ assertNull(testClass2["whatever"])
+ expect("TestApTrueExtraValid(extra=content, anything=another)") { testClass2.toString() }
+
+ assertFailsWith {
+ TestApTrueExtraValid(mapOf(
+ "anything" to "another",
+ ))
+ }.let {
+ expect("required property missing - extra") { it.message }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraValid(mapOf(
+ "extra" to 123,
+ ))
+ }.let {
+ expect("extra is not the correct type, expecting String") { it.message }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraValid(mapOf(
+ "extra" to "",
+ ))
+ }.let {
+ expect("extra length < minimum 1 - 0") { it.message }
+ }
+ }
+
+ @Test fun `should generate functional TestApTrueExtraOptValid`() {
+ val testClass1 = TestApTrueExtraOptValid(mapOf(
+ "extra" to "content",
+ ))
+ expect("content") { testClass1.extra }
+ assertNull(testClass1["whatever"])
+ expect("TestApTrueExtraOptValid(extra=content)") { testClass1.toString() }
+
+ val testClass2 = TestApTrueExtraOptValid(mapOf(
+ "extra" to "content",
+ "anything" to "another",
+ ))
+ expect("content") { testClass2.extra }
+ expect("another") { testClass2["anything"] }
+ assertNull(testClass2["whatever"])
+ expect("TestApTrueExtraOptValid(extra=content, anything=another)") { testClass2.toString() }
+
+ val testClass3 = TestApTrueExtraOptValid(mapOf(
+ "extra" to null,
+ ))
+ assertNull(testClass3.extra)
+ assertNull(testClass3["whatever"])
+ expect("TestApTrueExtraOptValid(extra=null)") { testClass3.toString() }
+
+ val testClass4 = TestApTrueExtraOptValid(emptyMap())
+ assertNull(testClass4.extra)
+ assertNull(testClass4["whatever"])
+ expect("TestApTrueExtraOptValid()") { testClass4.toString() }
+
+ val testClass5 = TestApTrueExtraOptValid(mapOf(
+ "anything" to "another",
+ ))
+ assertNull(testClass5.extra)
+ expect("another") { testClass5["anything"] }
+ assertNull(testClass5["whatever"])
+ expect("TestApTrueExtraOptValid(anything=another)") { testClass5.toString() }
+
+ assertFailsWith {
+ TestApTrueExtraOptValid(mapOf(
+ "extra" to 123,
+ ))
+ }.let {
+ expect("extra is not the correct type, expecting String?") { it.message }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraOptValid(mapOf(
"extra" to "",
))
}.let {
@@ -182,6 +317,170 @@ class AdditionalPropertiesFunctionalityTest {
}
}
+ @Test fun `should generate functional TestApTrueExtraArray`() {
+ with(TestApTrueExtraArray(mapOf(
+ "extra" to listOf("alpha", "beta"),
+ ))) {
+ with(extra) {
+ assertIs>(this)
+ expect(2) { size }
+ expect("alpha") { this[0] }
+ expect("beta") { this[1] }
+ }
+ assertNull(this["whatever"])
+ expect("TestApTrueExtraArray(extra=[alpha, beta])") { toString() }
+ }
+
+ with(TestApTrueExtraArray(mapOf(
+ "extra" to listOf("alpha", "beta"),
+ "anything" to "another",
+ ))) {
+ with(extra) {
+ assertIs>(this)
+ expect(2) { size }
+ expect("alpha") { this[0] }
+ expect("beta") { this[1] }
+ }
+ expect("another") { this["anything"] }
+ assertNull(this["whatever"])
+ expect("TestApTrueExtraArray(extra=[alpha, beta], anything=another)") { toString() }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraArray(emptyMap())
+ }.let {
+ expect("required property missing - extra") { it.message }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraArray(mapOf(
+ "extra" to "wrong",
+ ))
+ }.let {
+ expect("extra is not the correct type, expecting List") { it.message }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraArray(mapOf(
+ "extra" to listOf(123, 456),
+ ))
+ }.let {
+ expect("extra item is not the correct type, expecting String") { it.message }
+ }
+ }
+
+ @Test fun `should generate functional TestApTrueExtraArrayOpt`() {
+ with(TestApTrueExtraArrayOpt(mapOf(
+ "extra" to listOf("alpha", "beta"),
+ ))) {
+ with(extra) {
+ assertIs>(this)
+ expect(2) { size }
+ expect("alpha") { this[0] }
+ expect("beta") { this[1] }
+ }
+ assertNull(this["whatever"])
+ expect("TestApTrueExtraArrayOpt(extra=[alpha, beta])") { toString() }
+ }
+
+ with(TestApTrueExtraArrayOpt(mapOf(
+ "extra" to listOf("alpha", "beta"),
+ "anything" to "another",
+ ))) {
+ with(extra) {
+ assertIs>(this)
+ expect(2) { size }
+ expect("alpha") { this[0] }
+ expect("beta") { this[1] }
+ }
+ expect("another") { this["anything"] }
+ assertNull(this["whatever"])
+ expect("TestApTrueExtraArrayOpt(extra=[alpha, beta], anything=another)") { toString() }
+ }
+
+ with(TestApTrueExtraArrayOpt(emptyMap())) {
+ assertNull(this["extra"])
+ assertNull(this["whatever"])
+ expect("TestApTrueExtraArrayOpt()") { toString() }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraArrayOpt(mapOf(
+ "extra" to "wrong",
+ ))
+ }.let {
+ expect("extra is not the correct type, expecting List?") { it.message }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraArrayOpt(mapOf(
+ "extra" to listOf(123, 456),
+ ))
+ }.let {
+ expect("extra item is not the correct type, expecting String") { it.message }
+ }
+ }
+
+ @Test fun `should generate functional TestApTrueExtraArrayOptValid`() {
+ with(TestApTrueExtraArrayOptValid(mapOf(
+ "extra" to listOf("alpha", "beta"),
+ ))) {
+ with(extra) {
+ assertIs>(this)
+ expect(2) { size }
+ expect("alpha") { this[0] }
+ expect("beta") { this[1] }
+ }
+ assertNull(this["whatever"])
+ expect("TestApTrueExtraArrayOptValid(extra=[alpha, beta])") { toString() }
+ }
+
+ with(TestApTrueExtraArrayOptValid(mapOf(
+ "extra" to listOf("alpha", "beta"),
+ "anything" to "another",
+ ))) {
+ with(extra) {
+ assertIs>(this)
+ expect(2) { size }
+ expect("alpha") { this[0] }
+ expect("beta") { this[1] }
+ }
+ expect("another") { this["anything"] }
+ assertNull(this["whatever"])
+ expect("TestApTrueExtraArrayOptValid(extra=[alpha, beta], anything=another)") { toString() }
+ }
+
+ with(TestApTrueExtraArrayOptValid(emptyMap())) {
+ assertNull(this["extra"])
+ assertNull(this["whatever"])
+ expect("TestApTrueExtraArrayOptValid()") { toString() }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraArrayOptValid(mapOf(
+ "extra" to "wrong",
+ ))
+ }.let {
+ expect("extra is not the correct type, expecting List?") { it.message }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraArrayOptValid(mapOf(
+ "extra" to listOf(123, 456),
+ ))
+ }.let {
+ expect("extra item is not the correct type, expecting String") { it.message }
+ }
+
+ assertFailsWith {
+ TestApTrueExtraArrayOptValid(mapOf(
+ "extra" to listOf("alpha", ""),
+ ))
+ }.let {
+ expect("extra item length < minimum 1 - 0") { it.message }
+ }
+ }
+
@Test fun `should generate functional TestAdditionalPropertiesSchemaExtra`() {
val testClass1 = TestAdditionalPropertiesSchemaExtra(mapOf(
"extra" to "content",
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestAdditionalPropertiesSchemaExtra3.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestAdditionalPropertiesSchemaExtra3.kt
index 03f9245..780584b 100644
--- a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestAdditionalPropertiesSchemaExtra3.kt
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestAdditionalPropertiesSchemaExtra3.kt
@@ -23,8 +23,8 @@ class TestAdditionalPropertiesSchemaExtra3(
require(extra.isNotEmpty()) { "extra length < minimum 1 - ${extra.length}" }
}
if (cg_map.containsKey("extra2")) {
- require(cg_map["extra2"] is Int) { "extra2 is not the correct type, expecting Int?" }
- (cg_map["extra2"] as Int).let { extra2 ->
+ require(cg_map["extra2"] is Int?) { "extra2 is not the correct type, expecting Int?" }
+ (cg_map["extra2"] as Int?)?.let { extra2 ->
require(extra2 in 0..99) { "extra2 not in range 0..99 - $extra2" }
}
}
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApFalsePatternExtraOpt.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApFalsePatternExtraOpt.kt
index a0e1ff4..c41b3b2 100644
--- a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApFalsePatternExtraOpt.kt
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApFalsePatternExtraOpt.kt
@@ -18,8 +18,8 @@ class TestApFalsePatternExtraOpt(
init {
if (cg_map.containsKey("extra")) {
- require(cg_map["extra"] is String) { "extra is not the correct type, expecting String?" }
- (cg_map["extra"] as String).let { extra ->
+ require(cg_map["extra"] is String?) { "extra is not the correct type, expecting String?" }
+ (cg_map["extra"] as String?)?.let { extra ->
require(extra.isNotEmpty()) { "extra length < minimum 1 - ${extra.length}" }
}
}
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtra.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtra.kt
index 72a2d98..11c9b10 100644
--- a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtra.kt
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtra.kt
@@ -19,9 +19,6 @@ class TestApTrueExtra(
init {
require(cg_map.containsKey("extra")) { "required property missing - extra" }
require(cg_map["extra"] is String) { "extra is not the correct type, expecting String" }
- (cg_map["extra"] as String).let { extra ->
- require(extra.isNotEmpty()) { "extra length < minimum 1 - ${extra.length}" }
- }
}
val extra: String by cg_map
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraArrayOpt.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraArrayOpt.kt
new file mode 100644
index 0000000..45aca42
--- /dev/null
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraArrayOpt.kt
@@ -0,0 +1,38 @@
+/*
+ * TestApTrueExtraArrayOpt.kt
+ *
+ * This code was generated by json-kotlin-schema-codegen - JSON Schema Code Generator
+ * See https://github.com/pwall567/json-kotlin-schema-codegen
+ *
+ * It is not advisable to modify generated code as any modifications will be lost
+ * when the generation process is re-run.
+ */
+package net.pwall.json.schema.codegen.test.kotlin
+
+/**
+ * Test use of additionalProperties true with optional extra list field.
+ */
+class TestApTrueExtraArrayOpt(
+ private val cg_map: Map
+) : Map by cg_map {
+
+ init {
+ if (cg_map.containsKey("extra")) {
+ require(cg_map["extra"] is List<*>) { "extra is not the correct type, expecting List?" }
+ (cg_map["extra"] as List<*>).forEach { cg_0 ->
+ require(cg_0 is String) { "extra item is not the correct type, expecting String" }
+ }
+ }
+ }
+
+ val extra: List?
+ @Suppress("unchecked_cast")
+ get() = cg_map["extra"] as List?
+
+ override fun toString(): String = "TestApTrueExtraArrayOpt(${cg_map.entries.joinToString { "${it.key}=${it.value}" }})"
+
+ override fun equals(other: Any?): Boolean = this === other || other is TestApTrueExtraArrayOpt && cg_map == other.cg_map
+
+ override fun hashCode(): Int = cg_map.hashCode()
+
+}
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraArrayOptValid.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraArrayOptValid.kt
new file mode 100644
index 0000000..cacda17
--- /dev/null
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraArrayOptValid.kt
@@ -0,0 +1,39 @@
+/*
+ * TestApTrueExtraArrayOptValid.kt
+ *
+ * This code was generated by json-kotlin-schema-codegen - JSON Schema Code Generator
+ * See https://github.com/pwall567/json-kotlin-schema-codegen
+ *
+ * It is not advisable to modify generated code as any modifications will be lost
+ * when the generation process is re-run.
+ */
+package net.pwall.json.schema.codegen.test.kotlin
+
+/**
+ * Test use of additionalProperties true with optional extra list field with item validation.
+ */
+class TestApTrueExtraArrayOptValid(
+ private val cg_map: Map
+) : Map by cg_map {
+
+ init {
+ if (cg_map.containsKey("extra")) {
+ require(cg_map["extra"] is List<*>) { "extra is not the correct type, expecting List?" }
+ (cg_map["extra"] as List<*>).forEach { cg_0 ->
+ require(cg_0 is String) { "extra item is not the correct type, expecting String" }
+ require(cg_0.isNotEmpty()) { "extra item length < minimum 1 - ${cg_0.length}" }
+ }
+ }
+ }
+
+ val extra: List?
+ @Suppress("unchecked_cast")
+ get() = cg_map["extra"] as List?
+
+ override fun toString(): String = "TestApTrueExtraArrayOptValid(${cg_map.entries.joinToString { "${it.key}=${it.value}" }})"
+
+ override fun equals(other: Any?): Boolean = this === other || other is TestApTrueExtraArrayOptValid && cg_map == other.cg_map
+
+ override fun hashCode(): Int = cg_map.hashCode()
+
+}
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraNested.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraNested.kt
index 9c3b711..26783bd 100644
--- a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraNested.kt
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraNested.kt
@@ -22,7 +22,7 @@ class TestApTrueExtraNested(
require(cg_map.containsKey("codes")) { "required property missing - codes" }
require(cg_map["codes"] is Codes) { "codes is not the correct type, expecting Codes" }
if (cg_map.containsKey("empty"))
- require(cg_map["empty"] is Empty) { "empty is not the correct type, expecting Empty?" }
+ require(cg_map["empty"] is Empty?) { "empty is not the correct type, expecting Empty?" }
}
/** Extra data. */
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraOptValid.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraOptValid.kt
new file mode 100644
index 0000000..6b9dd72
--- /dev/null
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraOptValid.kt
@@ -0,0 +1,37 @@
+/*
+ * TestApTrueExtraOptValid.kt
+ *
+ * This code was generated by json-kotlin-schema-codegen - JSON Schema Code Generator
+ * See https://github.com/pwall567/json-kotlin-schema-codegen
+ *
+ * It is not advisable to modify generated code as any modifications will be lost
+ * when the generation process is re-run.
+ */
+package net.pwall.json.schema.codegen.test.kotlin
+
+/**
+ * Test use of additionalProperties true with optional extra fields with validation.
+ */
+class TestApTrueExtraOptValid(
+ private val cg_map: Map
+) : Map by cg_map {
+
+ init {
+ if (cg_map.containsKey("extra")) {
+ require(cg_map["extra"] is String?) { "extra is not the correct type, expecting String?" }
+ (cg_map["extra"] as String?)?.let { extra ->
+ require(extra.isNotEmpty()) { "extra length < minimum 1 - ${extra.length}" }
+ }
+ }
+ }
+
+ val extra: String?
+ get() = cg_map["extra"] as String?
+
+ override fun toString(): String = "TestApTrueExtraOptValid(${cg_map.entries.joinToString { "${it.key}=${it.value}" }})"
+
+ override fun equals(other: Any?): Boolean = this === other || other is TestApTrueExtraOptValid && cg_map == other.cg_map
+
+ override fun hashCode(): Int = cg_map.hashCode()
+
+}
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraOptional.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraOptional.kt
new file mode 100644
index 0000000..c7af994
--- /dev/null
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraOptional.kt
@@ -0,0 +1,33 @@
+/*
+ * TestApTrueExtraOptional.kt
+ *
+ * This code was generated by json-kotlin-schema-codegen - JSON Schema Code Generator
+ * See https://github.com/pwall567/json-kotlin-schema-codegen
+ *
+ * It is not advisable to modify generated code as any modifications will be lost
+ * when the generation process is re-run.
+ */
+package net.pwall.json.schema.codegen.test.kotlin
+
+/**
+ * Test use of additionalProperties true with optional extra fields.
+ */
+class TestApTrueExtraOptional(
+ private val cg_map: Map
+) : Map by cg_map {
+
+ init {
+ if (cg_map.containsKey("extra"))
+ require(cg_map["extra"] is String?) { "extra is not the correct type, expecting String?" }
+ }
+
+ val extra: String?
+ get() = cg_map["extra"] as String?
+
+ override fun toString(): String = "TestApTrueExtraOptional(${cg_map.entries.joinToString { "${it.key}=${it.value}" }})"
+
+ override fun equals(other: Any?): Boolean = this === other || other is TestApTrueExtraOptional && cg_map == other.cg_map
+
+ override fun hashCode(): Int = cg_map.hashCode()
+
+}
diff --git a/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraValid.kt b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraValid.kt
new file mode 100644
index 0000000..85597b9
--- /dev/null
+++ b/src/test/kotlin/net/pwall/json/schema/codegen/test/kotlin/TestApTrueExtraValid.kt
@@ -0,0 +1,35 @@
+/*
+ * TestApTrueExtraValid.kt
+ *
+ * This code was generated by json-kotlin-schema-codegen - JSON Schema Code Generator
+ * See https://github.com/pwall567/json-kotlin-schema-codegen
+ *
+ * It is not advisable to modify generated code as any modifications will be lost
+ * when the generation process is re-run.
+ */
+package net.pwall.json.schema.codegen.test.kotlin
+
+/**
+ * Test use of additionalProperties true with extra fields with validation.
+ */
+class TestApTrueExtraValid(
+ private val cg_map: Map
+) : Map by cg_map {
+
+ init {
+ require(cg_map.containsKey("extra")) { "required property missing - extra" }
+ require(cg_map["extra"] is String) { "extra is not the correct type, expecting String" }
+ (cg_map["extra"] as String).let { extra ->
+ require(extra.isNotEmpty()) { "extra length < minimum 1 - ${extra.length}" }
+ }
+ }
+
+ val extra: String by cg_map
+
+ override fun toString(): String = "TestApTrueExtraValid(${cg_map.entries.joinToString { "${it.key}=${it.value}" }})"
+
+ override fun equals(other: Any?): Boolean = this === other || other is TestApTrueExtraValid && cg_map == other.cg_map
+
+ override fun hashCode(): Int = cg_map.hashCode()
+
+}
diff --git a/src/test/resources/test-ap-true-extra-array-opt-valid.schema.json b/src/test/resources/test-ap-true-extra-array-opt-valid.schema.json
new file mode 100644
index 0000000..46ac0f2
--- /dev/null
+++ b/src/test/resources/test-ap-true-extra-array-opt-valid.schema.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "http://json-schema.org/draft/2019-09/schema",
+ "$id": "http://pwall.net/test-ap-true-extra-array-opt-valid",
+ "description": "Test use of additionalProperties true with optional extra list field with item validation.",
+ "type": "object",
+ "properties": {
+ "extra": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "additionalProperties": true
+}
diff --git a/src/test/resources/test-ap-true-extra-array-opt.schema.json b/src/test/resources/test-ap-true-extra-array-opt.schema.json
new file mode 100644
index 0000000..8410720
--- /dev/null
+++ b/src/test/resources/test-ap-true-extra-array-opt.schema.json
@@ -0,0 +1,15 @@
+{
+ "$schema": "http://json-schema.org/draft/2019-09/schema",
+ "$id": "http://pwall.net/test-ap-true-extra-array-opt",
+ "description": "Test use of additionalProperties true with optional extra list field.",
+ "type": "object",
+ "properties": {
+ "extra": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "additionalProperties": true
+}
diff --git a/src/test/resources/test-ap-true-extra-opt-valid.schema.json b/src/test/resources/test-ap-true-extra-opt-valid.schema.json
new file mode 100644
index 0000000..e74bd4a
--- /dev/null
+++ b/src/test/resources/test-ap-true-extra-opt-valid.schema.json
@@ -0,0 +1,13 @@
+{
+ "$schema": "http://json-schema.org/draft/2019-09/schema",
+ "$id": "http://pwall.net/test-ap-true-extra-opt-valid",
+ "description": "Test use of additionalProperties true with optional extra fields with validation.",
+ "type": "object",
+ "properties": {
+ "extra": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "additionalProperties": true
+}
diff --git a/src/test/resources/test-ap-true-extra-optional.schema.json b/src/test/resources/test-ap-true-extra-optional.schema.json
new file mode 100644
index 0000000..06f502b
--- /dev/null
+++ b/src/test/resources/test-ap-true-extra-optional.schema.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "http://json-schema.org/draft/2019-09/schema",
+ "$id": "http://pwall.net/test-ap-true-extra-optional",
+ "description": "Test use of additionalProperties true with optional extra fields.",
+ "type": "object",
+ "properties": {
+ "extra": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": true
+}
diff --git a/src/test/resources/test-ap-true-extra-valid.schema.json b/src/test/resources/test-ap-true-extra-valid.schema.json
new file mode 100644
index 0000000..c4f85b0
--- /dev/null
+++ b/src/test/resources/test-ap-true-extra-valid.schema.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "http://json-schema.org/draft/2019-09/schema",
+ "$id": "http://pwall.net/test-ap-true-extra-valid",
+ "description": "Test use of additionalProperties true with extra fields with validation.",
+ "type": "object",
+ "properties": {
+ "extra": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [ "extra" ],
+ "additionalProperties": true
+}
diff --git a/src/test/resources/test-ap-true-extra.schema.json b/src/test/resources/test-ap-true-extra.schema.json
index 4b68d5e..6b0767b 100644
--- a/src/test/resources/test-ap-true-extra.schema.json
+++ b/src/test/resources/test-ap-true-extra.schema.json
@@ -5,8 +5,7 @@
"type": "object",
"properties": {
"extra": {
- "type": "string",
- "minLength": 1
+ "type": "string"
}
},
"required": [ "extra" ],