Skip to content

Commit 852f61b

Browse files
committed
SchemaLoader now handles nullable schema attribute
* added `nullable` attribute to the `Schema` class as a Boolean, where - Boolean.TRUE means explicit nullability - Boolean.FALSE means explicit non-nullability - null should probably mean implicit non-nullability * adding `nullableSupport` as a feature flag to `SchemaLoader` class * the "nullable" flag from the schema JSON is mapped to `Schema#nullable` if and only if the `nullableSupport` flag is on. Tests added verifying it.
1 parent 9bacceb commit 852f61b

File tree

5 files changed

+74
-3
lines changed

5 files changed

+74
-3
lines changed

core/src/main/java/org/everit/json/schema/Schema.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public abstract static class Builder<S extends Schema> {
3131

3232
private Object defaultValue;
3333

34+
private Boolean nullable = null;
35+
3436
public Builder<S> title(String title) {
3537
this.title = title;
3638
return this;
@@ -56,10 +58,15 @@ public Builder<S> defaultValue(Object defaultValue) {
5658
return this;
5759
}
5860

61+
public Builder<S> nullable(Boolean nullable) {
62+
this.nullable = nullable;
63+
return this;
64+
}
65+
5966
public abstract S build();
6067

61-
}
6268

69+
}
6370
private final String title;
6471

6572
private final String description;
@@ -70,6 +77,8 @@ public Builder<S> defaultValue(Object defaultValue) {
7077

7178
private final Object defaultValue;
7279

80+
private final Boolean nullable;
81+
7382
/**
7483
* Constructor.
7584
*
@@ -82,6 +91,7 @@ protected Schema(Builder<?> builder) {
8291
this.id = builder.id;
8392
this.schemaLocation = builder.schemaLocation;
8493
this.defaultValue = builder.defaultValue;
94+
this.nullable = builder.nullable;
8595
}
8696

8797
/**
@@ -189,6 +199,9 @@ public boolean hasDefaultValue() {
189199
return this.defaultValue != null;
190200
}
191201

202+
public Boolean isNullable() {
203+
return nullable;
204+
}
192205
/**
193206
* Describes the instance as a JSONObject to {@code writer}.
194207
* <p>

core/src/main/java/org/everit/json/schema/loader/LoaderConfig.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,20 @@ static LoaderConfig defaultV4Config() {
2525

2626
final boolean useDefaults;
2727

28+
final boolean nullableSupport;
29+
2830
LoaderConfig(SchemaClient httpClient, Map<String, FormatValidator> formatValidators,
2931
SpecificationVersion specVersion, boolean useDefaults) {
32+
this(httpClient, formatValidators, specVersion, useDefaults, false);
33+
}
34+
35+
LoaderConfig(SchemaClient httpClient, Map<String, FormatValidator> formatValidators,
36+
SpecificationVersion specVersion, boolean useDefaults, boolean nullableSupport) {
3037
this.httpClient = requireNonNull(httpClient, "httpClient cannot be null");
3138
this.formatValidators = requireNonNull(formatValidators, "formatValidators cannot be null");
3239
this.specVersion = requireNonNull(specVersion, "specVersion cannot be null");
3340
this.useDefaults = useDefaults;
41+
this.nullableSupport = nullableSupport;
3442
}
3543

3644
}

core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public static class SchemaLoaderBuilder {
7171

7272
boolean useDefaults = false;
7373

74+
private boolean nullableSupport = false;
75+
7476
/**
7577
* Registers a format validator with the name returned by {@link FormatValidator#formatName()}.
7678
*
@@ -188,6 +190,10 @@ public SchemaLoaderBuilder useDefaults(boolean useDefaults) {
188190
return this;
189191
}
190192

193+
public SchemaLoaderBuilder nullableSupport(boolean nullableSupport) {
194+
this.nullableSupport = nullableSupport;
195+
return this;
196+
}
191197
}
192198

193199
private static final List<String> NUMBER_SCHEMA_PROPS = asList("minimum", "maximum",
@@ -266,7 +272,11 @@ public SchemaLoader(SchemaLoaderBuilder builder) {
266272
specVersion = SpecificationVersion.getByMetaSchemaUrl((String) schemaValue);
267273
}
268274
}
269-
this.config = new LoaderConfig(builder.httpClient, builder.formatValidators, specVersion, builder.useDefaults);
275+
this.config = new LoaderConfig(builder.httpClient,
276+
builder.formatValidators,
277+
specVersion,
278+
builder.useDefaults,
279+
builder.nullableSupport);
270280
this.ls = new LoadingState(config,
271281
builder.pointerSchemas,
272282
builder.rootSchemaJson == null ? builder.schemaJson : builder.rootSchemaJson,
@@ -362,6 +372,9 @@ private Schema.Builder loadSchemaObject(JsonObject o) {
362372
ls.schemaJson().maybe(config.specVersion.idKeyword()).map(JsonValue::requireString).ifPresent(builder::id);
363373
ls.schemaJson().maybe("title").map(JsonValue::requireString).ifPresent(builder::title);
364374
ls.schemaJson().maybe("description").map(JsonValue::requireString).ifPresent(builder::description);
375+
if (config.nullableSupport) {
376+
ls.schemaJson().maybe("nullable").map(JsonValue::requireBoolean).ifPresent(builder::nullable);
377+
}
365378
if (config.useDefaults) {
366379
ls.schemaJson().maybe("default").map(JsonValue::deepToOrgJson).ifPresent(builder::defaultValue);
367380
}

core/src/test/java/org/everit/json/schema/loader/SchemaLoaderTest.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static org.junit.Assert.assertEquals;
1010
import static org.junit.Assert.assertFalse;
1111
import static org.junit.Assert.assertNotNull;
12+
import static org.junit.Assert.assertNull;
1213
import static org.junit.Assert.assertTrue;
1314
import static org.mockito.Mockito.mock;
1415
import static org.mockito.Mockito.when;
@@ -353,7 +354,7 @@ public void stringSchemaWithFormat() {
353354
public void tupleSchema() {
354355
ArraySchema actual = (ArraySchema) SchemaLoader.load(get("tupleSchema"));
355356
assertFalse(actual.permitsAdditionalItems());
356-
Assert.assertNull(actual.getAllItemSchema());
357+
assertNull(actual.getAllItemSchema());
357358
assertEquals(2, actual.getItemSchemas().size());
358359
assertEquals(BooleanSchema.INSTANCE, actual.getItemSchemas().get(0));
359360
assertEquals(NullSchema.INSTANCE, actual.getItemSchemas().get(1));
@@ -579,4 +580,28 @@ public void applyDefaultNullTest() {
579580

580581
assertEquals(JSONObject.NULL, obj.get("nullDefault"));
581582
}
583+
584+
@Test
585+
public void nullableBooleansAre_Loaded_withNullableSupport() {
586+
SchemaLoader loader = SchemaLoader.builder()
587+
.nullableSupport(true)
588+
.schemaJson(get("nullableSupport"))
589+
.build();
590+
ObjectSchema actual = (ObjectSchema) loader.load().build();
591+
Schema nullableSchema = actual.getPropertySchemas().get("isNullable");
592+
Schema nonNulableSchema = actual.getPropertySchemas().get("nonNullable");
593+
594+
assertTrue(nullableSchema.isNullable());
595+
assertFalse(nonNulableSchema.isNullable());
596+
}
597+
598+
@Test
599+
public void nullableBooleansAre_NotLoaded_withoutNullableSupport() {
600+
ObjectSchema actual = (ObjectSchema) SchemaLoader.load(get("nullableSupport"));
601+
Schema nullableSchema = actual.getPropertySchemas().get("isNullable");
602+
Schema nonNulableSchema = actual.getPropertySchemas().get("nonNullable");
603+
604+
assertNull(nullableSchema.isNullable());
605+
assertNull(nonNulableSchema.isNullable());
606+
}
582607
}

core/src/test/resources/org/everit/jsonvalidator/testschemas.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,5 +587,17 @@
587587
"default": null
588588
}
589589
}
590+
},
591+
"nullableSupport": {
592+
"properties": {
593+
"nonNullable": {
594+
"type": "number",
595+
"nullable": false
596+
},
597+
"isNullable": {
598+
"type": "string",
599+
"nullable": true
600+
}
601+
}
590602
}
591603
}

0 commit comments

Comments
 (0)