Skip to content

Commit cbc4caa

Browse files
authored
Allow for default dialect id not to be specified and throw an exception (#1212)
1 parent 3f419f4 commit cbc4caa

File tree

4 files changed

+72
-3
lines changed

4 files changed

+72
-3
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,16 @@ List<Error> errors = schema.validate(input, InputFormat.JSON, executionContext -
339339
});
340340
```
341341

342+
### Require schema dialect to be specified
343+
344+
The specification allows for the `$schema` keyword not to be specified, in which case the schema will default to the default dialect specified.
345+
346+
The following example creates a `SchemaRegistry` that does not specify a default dialect and will throw a `MissingSchemaKeywordException` if the schema does not specify a dialect using the `$schema` keyword.
347+
348+
```java
349+
SchemaRegistry registry = SchemaRegistry.builder().dialectRegistry(new BasicDialectRegistry(Dialects.getDraft202012())).build();
350+
```
351+
342352
### Results and output formats
343353

344354
#### Results
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.networknt.schema;
18+
19+
/**
20+
* Thrown when the $schema keyword is expected as no default dialect id was
21+
* specified.
22+
*/
23+
public class MissingSchemaKeywordException extends SchemaException {
24+
private static final long serialVersionUID = 1L;
25+
26+
public MissingSchemaKeywordException(String message) {
27+
super(message);
28+
}
29+
}

src/main/java/com/networknt/schema/SchemaRegistry.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,6 @@ public SchemaRegistry build() {
218218

219219
private SchemaRegistry(NodeReader nodeReader, String defaultDialectId, SchemaLoader schemaLoader,
220220
boolean schemaCacheEnabled, DialectRegistry dialectRegistry, SchemaRegistryConfig schemaRegistryConfig) {
221-
if (defaultDialectId == null || defaultDialectId.trim().isEmpty()) {
222-
throw new IllegalArgumentException("defaultDialectId must not be null or empty");
223-
}
224221
this.nodeReader = nodeReader != null ? nodeReader : BasicNodeReader.getInstance();
225222
this.defaultDialectId = defaultDialectId;
226223
this.schemaLoader = schemaLoader != null ? schemaLoader : SchemaLoader.getDefault();
@@ -549,6 +546,10 @@ private Dialect getDialectOrDefault(final JsonNode schemaNode) {
549546
throw new SchemaException("Unknown dialect: " + iriNode);
550547
}
551548
final String iri = iriNode == null || iriNode.isNull() ? defaultDialectId : iriNode.textValue();
549+
if (iri == null) {
550+
throw new MissingSchemaKeywordException(
551+
"The $schema keyword that indicates the schema dialect must be specified.");
552+
}
552553
return getDialect(iri);
553554
}
554555

src/test/java/com/networknt/schema/SchemaRegistryTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525

2626
import org.junit.jupiter.api.Test;
2727

28+
import com.networknt.schema.dialect.BasicDialectRegistry;
2829
import com.networknt.schema.dialect.Dialect;
30+
import com.networknt.schema.dialect.Dialects;
2931

3032
/**
3133
* Tests for JsonSchemaFactory.
@@ -87,4 +89,31 @@ public void run() {
8789
});
8890
assertFalse(failed.get());
8991
}
92+
93+
@Test
94+
void noDefaultDialect() {
95+
SchemaRegistry registry = SchemaRegistry.builder()
96+
.dialectRegistry(new BasicDialectRegistry(Dialects.getDraft202012())).build();
97+
assertThrows(MissingSchemaKeywordException.class, () -> {
98+
registry.getSchema("{\"type\":\"object\"}");
99+
});
100+
}
101+
102+
@Test
103+
void noDefaultDialectButSchemaSpecified() {
104+
SchemaRegistry registry = SchemaRegistry.builder()
105+
.dialectRegistry(new BasicDialectRegistry(Dialects.getDraft202012())).build();
106+
assertDoesNotThrow(() -> {
107+
registry.getSchema("{\"$schema\":\"https://json-schema.org/draft/2020-12/schema\",\"type\":\"object\"}");
108+
});
109+
}
110+
111+
@Test
112+
void noDefaultDialectButSchemaSpecifiedButNotInRegistry() {
113+
SchemaRegistry registry = SchemaRegistry.builder()
114+
.dialectRegistry(new BasicDialectRegistry(Dialects.getDraft201909())).build();
115+
assertThrows(InvalidSchemaException.class, () -> {
116+
registry.getSchema("{\"$schema\":\"https://json-schema.org/draft/2020-12/schema\",\"type\":\"object\"}");
117+
});
118+
}
90119
}

0 commit comments

Comments
 (0)