diff --git a/core/src/main/java/org/everit/json/schema/Schema.java b/core/src/main/java/org/everit/json/schema/Schema.java index 70fe23a51..deab99ceb 100644 --- a/core/src/main/java/org/everit/json/schema/Schema.java +++ b/core/src/main/java/org/everit/json/schema/Schema.java @@ -1,104 +1,22 @@ package org.everit.json.schema; -import static java.util.Collections.unmodifiableMap; +import org.everit.json.schema.internal.JSONPrinter; +import org.json.JSONWriter; import java.io.StringWriter; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; -import org.everit.json.schema.internal.JSONPrinter; -import org.json.JSONWriter; +import static java.util.Collections.unmodifiableMap; /** * Superclass of all other schema validator classes of this package. */ public abstract class Schema { - /** - * Abstract builder class for the builder classes of {@code Schema} subclasses. This builder is - * used to load the generic properties of all types of schemas like {@code title} or - * {@code description}. - * - * @param - * the type of the schema being built by the builder subclass. - */ - public abstract static class Builder { - - private String title; - - private String description; - - private String id; - - private SchemaLocation schemaLocation; - - private Object defaultValue; - - private Boolean nullable = null; - - private Boolean readOnly = null; - - private Boolean writeOnly = null; - - public Map unprocessedProperties = new HashMap<>(0); - - public Builder title(String title) { - this.title = title; - return this; - } - - public Builder description(String description) { - this.description = description; - return this; - } - - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * @deprecated Use {@link #schemaLocation(SchemaLocation)} instead. - */ - @Deprecated - public Builder schemaLocation(String schemaLocation) { - return schemaLocation(SchemaLocation.parseURI(schemaLocation)); - } - - public Builder schemaLocation(SchemaLocation location) { - this.schemaLocation = location; - return this; - } - - public Builder defaultValue(Object defaultValue) { - this.defaultValue = defaultValue; - return this; - } - - public Builder nullable(Boolean nullable) { - this.nullable = nullable; - return this; - } - - public Builder readOnly(Boolean readOnly) { - this.readOnly = readOnly; - return this; - } - - public Builder writeOnly(Boolean writeOnly) { - this.writeOnly = writeOnly; - return this; - } - - public Builder unprocessedProperties(Map unprocessedProperties) { - this.unprocessedProperties = unprocessedProperties; - return this; - } - - public abstract S build(); - - } + private final String examples; private final String title; @@ -113,14 +31,6 @@ public Builder unprocessedProperties(Map unprocessedPropertie private final Object defaultValue; - private final Boolean nullable; - - private final Boolean readOnly; - - private final Boolean writeOnly; - - private final Map unprocessedProperties; - /** * Constructor. * @@ -134,12 +44,43 @@ protected Schema(Builder builder) { this.schemaLocation = builder.schemaLocation == null ? null : builder.schemaLocation.toString(); this.location = builder.schemaLocation; this.defaultValue = builder.defaultValue; + this.examples = builder.examples; this.nullable = builder.nullable; this.readOnly = builder.readOnly; this.writeOnly = builder.writeOnly; this.unprocessedProperties = new HashMap<>(builder.unprocessedProperties); } + private final Boolean nullable; + + private final Boolean readOnly; + + private final Boolean writeOnly; + + private final Map unprocessedProperties; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o instanceof Schema) { + Schema schema = (Schema) o; + return schema.canEqual(this) && + Objects.equals(title, schema.title) && + Objects.equals(defaultValue, schema.defaultValue) && + Objects.equals(examples, schema.examples) && + Objects.equals(description, schema.description) && + Objects.equals(id, schema.id) && + Objects.equals(nullable, schema.nullable) && + Objects.equals(readOnly, schema.readOnly) && + Objects.equals(writeOnly, schema.writeOnly) && + Objects.equals(unprocessedProperties, schema.unprocessedProperties); + } else { + return false; + } + } + /** * Performs the schema validation. * @@ -199,29 +140,13 @@ public boolean definesProperty(String field) { } @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o instanceof Schema) { - Schema schema = (Schema) o; - return schema.canEqual(this) && - Objects.equals(title, schema.title) && - Objects.equals(defaultValue, schema.defaultValue) && - Objects.equals(description, schema.description) && - Objects.equals(id, schema.id) && - Objects.equals(nullable, schema.nullable) && - Objects.equals(readOnly, schema.readOnly) && - Objects.equals(writeOnly, schema.writeOnly) && - Objects.equals(unprocessedProperties, schema.unprocessedProperties); - } else { - return false; - } + public int hashCode() { + return Objects.hash(title, description, id, defaultValue, examples, nullable, readOnly, writeOnly, + unprocessedProperties); } - @Override - public int hashCode() { - return Objects.hash(title, description, id, defaultValue, nullable, readOnly, writeOnly, unprocessedProperties); + public String getExamples() { + return this.examples; } public String getTitle() { @@ -248,6 +173,103 @@ public Object getDefaultValue() { return this.defaultValue; } + /** + * Abstract builder class for the builder classes of {@code Schema} subclasses. This builder is + * used to load the generic properties of all types of schemas like {@code title} or + * {@code description}. + * + * @param + * the type of the schema being built by the builder subclass. + */ + public abstract static class Builder { + + private String title; + + private String description; + + private String id; + + private SchemaLocation schemaLocation; + + private Object defaultValue; + + private String examples; + + private Boolean nullable = null; + + private Boolean readOnly = null; + + private Boolean writeOnly = null; + + public Map unprocessedProperties = new HashMap<>(0); + + public Builder title(String title) { + this.title = title; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * @deprecated Use {@link #schemaLocation(SchemaLocation)} instead. + */ + @Deprecated + public Builder schemaLocation(String schemaLocation) { + return schemaLocation(SchemaLocation.parseURI(schemaLocation)); + } + + public Builder schemaLocation(SchemaLocation location) { + this.schemaLocation = location; + return this; + } + + public Builder defaultValue(Object defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public Builder examples(List examples) { + StringBuilder exampleBuilder = new StringBuilder("["); + for (String example : examples) { + exampleBuilder.append(example); + } + exampleBuilder.append("]"); + this.examples = examples.toString(); + return this; + } + + public Builder nullable(Boolean nullable) { + this.nullable = nullable; + return this; + } + + public Builder readOnly(Boolean readOnly) { + this.readOnly = readOnly; + return this; + } + + public Builder writeOnly(Boolean writeOnly) { + this.writeOnly = writeOnly; + return this; + } + + public Builder unprocessedProperties(Map unprocessedProperties) { + this.unprocessedProperties = unprocessedProperties; + return this; + } + + public abstract S build(); + + } + public boolean hasDefaultValue() { return this.defaultValue != null; } diff --git a/core/src/main/java/org/everit/json/schema/ToStringVisitor.java b/core/src/main/java/org/everit/json/schema/ToStringVisitor.java index a66d69bed..4000713d3 100644 --- a/core/src/main/java/org/everit/json/schema/ToStringVisitor.java +++ b/core/src/main/java/org/everit/json/schema/ToStringVisitor.java @@ -36,6 +36,7 @@ class ToStringVisitor extends Visitor { writer.ifPresent("description", schema.getDescription()); writer.ifPresent("nullable", schema.isNullable()); writer.ifPresent("default", schema.getDefaultValue()); + writer.ifPresent("examples", schema.getExamples()); writer.ifPresent("readOnly", schema.isReadOnly()); writer.ifPresent("writeOnly", schema.isWriteOnly()); super.visitSchema(schema); diff --git a/core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java b/core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java index 17090aa78..91b072886 100644 --- a/core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java +++ b/core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java @@ -11,6 +11,7 @@ import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -432,6 +433,9 @@ private AdjacentSchemaExtractionState loadCommonSchemaProperties(Schema.Builder consumedKeys.maybe(config.specVersion.idKeyword()).map(JsonValue::requireString).ifPresent(builder::id); consumedKeys.maybe("title").map(JsonValue::requireString).ifPresent(builder::title); consumedKeys.maybe("description").map(JsonValue::requireString).ifPresent(builder::description); + if(consumedKeys.maybe("examples").isPresent()) { + setExamples(builder, consumedKeys); + } if (ls.specVersion() == DRAFT_7) { consumedKeys.maybe("readOnly").map(JsonValue::requireBoolean).ifPresent(builder::readOnly); consumedKeys.maybe("writeOnly").map(JsonValue::requireBoolean).ifPresent(builder::writeOnly); @@ -448,6 +452,15 @@ private AdjacentSchemaExtractionState loadCommonSchemaProperties(Schema.Builder return state.reduce(new ExtractionResult(consumedKeys.collect(), emptyList())); } + private void setExamples(Schema.Builder builder, KeyConsumer consumedKeys) { + JsonArray jsonArray = consumedKeys.maybe("examples").get().requireArray(); + List examples= new ArrayList<>(); + for(int index = 0; index < jsonArray.length();index++){ + examples.add(jsonArray.at(index).requireString()); + } + builder.examples(examples); + } + /** * Populates a {@code Schema.Builder} instance from the {@code schemaJson} schema definition. * diff --git a/core/src/test/java/org/everit/json/schema/StringSchemaTest.java b/core/src/test/java/org/everit/json/schema/StringSchemaTest.java index 9c70cb28a..f10f1f379 100644 --- a/core/src/test/java/org/everit/json/schema/StringSchemaTest.java +++ b/core/src/test/java/org/everit/json/schema/StringSchemaTest.java @@ -117,6 +117,7 @@ public void equalsVerifier() { public void toStringTest() { JSONObject rawSchemaJson = ResourceLoader.DEFAULT.readObj("tostring/stringschema.json"); String actual = SchemaLoader.load(rawSchemaJson).toString(); + setExamplesAsString(rawSchemaJson); assertThat(new JSONObject(actual), sameJsonAs(rawSchemaJson)); } @@ -125,6 +126,7 @@ public void toStringWithNullableTrueTest() { JSONObject rawSchemaJson = ResourceLoader.DEFAULT.readObj("tostring/stringschema.json"); rawSchemaJson.put("nullable", true); String actual = loadWithNullableSupport(rawSchemaJson).toString(); + setExamplesAsString(rawSchemaJson); assertThat(new JSONObject(actual), sameJsonAs(rawSchemaJson)); } @@ -133,6 +135,7 @@ public void toStringWithNullableFalseTest() { JSONObject rawSchemaJson = ResourceLoader.DEFAULT.readObj("tostring/stringschema.json"); rawSchemaJson.put("nullable", false); String actual = loadWithNullableSupport(rawSchemaJson).toString(); + setExamplesAsString(rawSchemaJson); assertThat(new JSONObject(actual), sameJsonAs(rawSchemaJson)); } @@ -141,6 +144,7 @@ public void toStringNoFormat() { JSONObject rawSchemaJson = ResourceLoader.DEFAULT.readObj("tostring/stringschema.json"); rawSchemaJson.remove("format"); String actual = SchemaLoader.load(rawSchemaJson).toString(); + setExamplesAsString(rawSchemaJson); assertThat(new JSONObject(actual), sameJsonAs(rawSchemaJson)); } @@ -149,6 +153,7 @@ public void toStringNoExplicitType() { JSONObject rawSchemaJson = ResourceLoader.DEFAULT.readObj("tostring/stringschema.json"); rawSchemaJson.remove("type"); String actual = SchemaLoader.load(rawSchemaJson).toString(); + setExamplesAsString(rawSchemaJson); assertThat(new JSONObject(actual), sameJsonAs(rawSchemaJson)); } @@ -194,4 +199,20 @@ public void regexpFactoryIsUsedByLoader() { assertEquals(result.getRegexpPattern().getClass().getSimpleName(), "RE2JRegexp"); } + @Test + public void shouldHaveExamplesValue(){ + SchemaLoader loader = SchemaLoader.builder() + .regexpFactory(new RE2JRegexpFactory()) + .schemaJson(ResourceLoader.DEFAULT.readObj("tostring/stringschema.json")) + .build(); + + StringSchema result = (StringSchema) loader.load().build(); + + assertEquals("[example1, example2]",result.getExamples()); + } + + private void setExamplesAsString(JSONObject rawSchemaJson){ + rawSchemaJson.put("examples","[example1, example2]"); + } + } diff --git a/core/src/test/resources/org/everit/jsonvalidator/tostring/stringschema.json b/core/src/test/resources/org/everit/jsonvalidator/tostring/stringschema.json index 36f50421f..a13c58eda 100644 --- a/core/src/test/resources/org/everit/jsonvalidator/tostring/stringschema.json +++ b/core/src/test/resources/org/everit/jsonvalidator/tostring/stringschema.json @@ -3,5 +3,6 @@ "minLength": 0, "maxLength": 10, "pattern": "a.b*c", - "format": "date-time" + "format": "date-time", + "examples": ["example1","example2"] }