Skip to content

Commit fb28b47

Browse files
authored
Merge pull request #808 from OptimumCode/support-remote-schemas
Update kotlin-kmp-json-schema-validator: validator now supports remote schemes
2 parents 8ed8742 + 507a4ac commit fb28b47

File tree

2 files changed

+43
-63
lines changed

2 files changed

+43
-63
lines changed

src/main/kotlin/BowtieSampsonSchemaValidatorLauncher.kt

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import io.github.optimumcode.json.schema.ErrorCollector
22
import io.github.optimumcode.json.schema.JsonSchema
3+
import io.github.optimumcode.json.schema.JsonSchemaLoader
34
import io.github.optimumcode.json.schema.SchemaType
45
import kotlinx.serialization.encodeToString
56
import kotlinx.serialization.json.Json
7+
import kotlinx.serialization.json.JsonElement
8+
import kotlinx.serialization.json.JsonObject
9+
import kotlinx.serialization.json.jsonPrimitive
610
import java.io.BufferedReader
711
import java.io.BufferedWriter
812
import java.io.InputStreamReader
@@ -91,7 +95,7 @@ class BowtieSampsonSchemaValidatorLauncher(
9195

9296
@Suppress("detekt:TooGenericExceptionCaught")
9397
val schema = try {
94-
JsonSchema.fromJsonElement(schemaDefinition, currentDialect)
98+
loadSchema(command, schemaDefinition)
9599
} catch (ex: Exception) {
96100
writer.writeLine(
97101
json.encodeToString(
@@ -109,6 +113,38 @@ class BowtieSampsonSchemaValidatorLauncher(
109113
runCase(command, schema)
110114
}
111115

116+
private fun loadSchema(
117+
command: Command.Run,
118+
schemaDefinition: JsonElement,
119+
): JsonSchema = JsonSchemaLoader.create()
120+
.apply {
121+
currentDialect?.also(this::registerWellKnown)
122+
for ((uri, schema) in command.case.registry) {
123+
if (skipSchema(uri, schema)) {
124+
continue
125+
}
126+
@Suppress("detekt:TooGenericExceptionCaught")
127+
try {
128+
register(schema, uri)
129+
} catch (ex: Exception) {
130+
throw IllegalStateException("cannot register schema for URI '$uri'", ex)
131+
}
132+
}
133+
}.fromJsonElement(schemaDefinition, currentDialect)
134+
135+
private fun skipSchema(uri: String, schema: JsonElement): Boolean {
136+
if (uri.contains("draft4", ignoreCase = true)) {
137+
// skip draft4 schemas
138+
return true
139+
}
140+
// ignore schemas for unsupported drafts
141+
return schema is JsonObject &&
142+
schema["\$schema"]
143+
?.jsonPrimitive
144+
?.content
145+
.let { it != null && SchemaType.find(it) == null }
146+
}
147+
112148
private fun runCase(command: Command.Run, schema: JsonSchema) {
113149
val results: List<TestResult> = command.case.tests.map { test ->
114150
runCatching {

src/main/kotlin/TestFilters.kt

Lines changed: 6 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -20,52 +20,19 @@ fun getFilter(schemaType: SchemaType?): TestFilter =
2020
}
2121

2222
object TestFilterDraft7 : TestFilter {
23-
/**
24-
* All these cases are ignored because they contain remote refs
25-
* Library does not support them yet.
26-
*/
27-
private val IGNORED_CASES: Set<String> = hashSetOf(
28-
"validate definition against metaschema",
29-
"base URI change - change folder",
30-
"base URI change - change folder in subschema",
31-
"base URI change",
32-
"retrieved nested refs resolve relative to their URI not \$id",
33-
"\$ref to \$ref finds location-independent \$id",
34-
)
3523

3624
override fun shouldSkipCase(caseDescription: String): String? {
3725
return when {
3826
caseDescription.endsWith(" format") -> "the format keyword is not yet supported"
39-
caseDescription in IGNORED_CASES || caseDescription.contains("remote ref") ->
40-
"remote schema loading is not yet supported"
41-
4227
else -> null
4328
}
4429
}
4530
}
4631

4732
object TestFilterDraft201909 : TestFilter {
48-
/**
49-
* All these cases are ignored because they contain remote refs or meta schema
50-
* Library does not support them yet.
51-
*/
52-
private val IGNORED_CASES_WITH_REMOTE_REF: Set<String> = hashSetOf(
53-
"invalid anchors",
54-
"Invalid use of fragments in location-independent \$id",
55-
"Valid use of empty fragments in location-independent \$id",
56-
"Unnormalized \$ids are allowed but discouraged",
57-
"URN base URI with f-component",
58-
"remote HTTP ref with different \$id",
59-
"remote HTTP ref with different URN \$id",
60-
"remote HTTP ref with nested absolute ref",
61-
"\$ref to \$ref finds detached \$anchor",
33+
private val IGNORED_CASES_WITH_CUSTOM_META_SCHEMA: Set<String> = hashSetOf(
6234
"schema that uses custom metaschema with with no validation vocabulary",
6335
"ignore unrecognized optional vocabulary",
64-
"validate definition against metaschema",
65-
"retrieved nested refs resolve relative to their URI not \$id",
66-
"base URI change - change folder in subschema",
67-
"base URI change - change folder",
68-
"base URI change",
6936
)
7037

7138
private val IGNORE_CASES_WITH_MIN_CONTAINS_ZERO = setOf(
@@ -75,8 +42,8 @@ object TestFilterDraft201909 : TestFilter {
7542
override fun shouldSkipCase(caseDescription: String): String? {
7643
return when {
7744
caseDescription.endsWith(" format") -> "the format keyword is not yet supported"
78-
caseDescription in IGNORED_CASES_WITH_REMOTE_REF || caseDescription.contains("remote ref") ->
79-
"remote schema loading and meta schemas are not yet supported"
45+
caseDescription in IGNORED_CASES_WITH_CUSTOM_META_SCHEMA ->
46+
"vocabulary from custom meta-schemas is not supported yet"
8047
caseDescription in IGNORE_CASES_WITH_MIN_CONTAINS_ZERO ->
8148
"'minContains' does not affect contains work - at least one element must match 'contains' schema"
8249
else -> null
@@ -95,39 +62,16 @@ object TestFilterDraft201909 : TestFilter {
9562
}
9663

9764
object TestFilterDraft202012 : TestFilter {
98-
/**
99-
* All these cases are ignored because they contain remote refs or meta schema
100-
* Library does not support them yet.
101-
*/
102-
private val IGNORED_CASES_WITH_REMOTE_REF: Set<String> = hashSetOf(
103-
"invalid anchors",
104-
"Invalid use of fragments in location-independent \$id",
105-
"Valid use of empty fragments in location-independent \$id",
106-
"Unnormalized \$ids are allowed but discouraged",
107-
"URN base URI with f-component",
108-
"remote HTTP ref with different \$id",
109-
"remote HTTP ref with different URN \$id",
110-
"remote HTTP ref with nested absolute ref",
111-
"\$ref to \$ref finds detached \$anchor",
65+
private val IGNORED_CASES_WITH_CUSTOM_META_SCHEMA: Set<String> = hashSetOf(
11266
"schema that uses custom metaschema with with no validation vocabulary",
11367
"ignore unrecognized optional vocabulary",
114-
"validate definition against metaschema",
115-
"retrieved nested refs resolve relative to their URI not \$id",
116-
"base URI change - change folder in subschema",
117-
"base URI change - change folder",
118-
"base URI change",
119-
"strict-tree schema, guards against misspelled properties",
120-
"tests for implementation dynamic anchor and reference link",
121-
"\$ref and \$dynamicAnchor are independent of order - \$defs first",
122-
"\$ref and \$dynamicAnchor are independent of order - \$ref first",
123-
"\$ref to \$dynamicRef finds detached \$dynamicAnchor",
12468
)
12569

12670
override fun shouldSkipCase(caseDescription: String): String? {
12771
return when {
12872
caseDescription.endsWith(" format") -> "the format keyword is not yet supported"
129-
caseDescription in IGNORED_CASES_WITH_REMOTE_REF || caseDescription.contains("remote ref") ->
130-
"remote schema loading and meta schemas are not yet supported"
73+
caseDescription in IGNORED_CASES_WITH_CUSTOM_META_SCHEMA ->
74+
"vocabulary from custom meta-schemas is not supported yet"
13175
else -> null
13276
}
13377
}

0 commit comments

Comments
 (0)