Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provide examples field to set example value for a field. #356

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
254 changes: 138 additions & 116 deletions core/src/main/java/org/everit/json/schema/Schema.java
Original file line number Diff line number Diff line change
@@ -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 <S>
* the type of the schema being built by the builder subclass.
*/
public abstract static class Builder<S extends Schema> {

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<String, Object> unprocessedProperties = new HashMap<>(0);

public Builder<S> title(String title) {
this.title = title;
return this;
}

public Builder<S> description(String description) {
this.description = description;
return this;
}

public Builder<S> id(String id) {
this.id = id;
return this;
}

/**
* @deprecated Use {@link #schemaLocation(SchemaLocation)} instead.
*/
@Deprecated
public Builder<S> schemaLocation(String schemaLocation) {
return schemaLocation(SchemaLocation.parseURI(schemaLocation));
}

public Builder<S> schemaLocation(SchemaLocation location) {
this.schemaLocation = location;
return this;
}

public Builder<S> defaultValue(Object defaultValue) {
this.defaultValue = defaultValue;
return this;
}

public Builder<S> nullable(Boolean nullable) {
this.nullable = nullable;
return this;
}

public Builder<S> readOnly(Boolean readOnly) {
this.readOnly = readOnly;
return this;
}

public Builder<S> writeOnly(Boolean writeOnly) {
this.writeOnly = writeOnly;
return this;
}

public Builder<S> unprocessedProperties(Map<String, Object> unprocessedProperties) {
this.unprocessedProperties = unprocessedProperties;
return this;
}

public abstract S build();

}
private final String examples;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A parsed Object would be much more useful than a string.


private final String title;

Expand All @@ -113,14 +31,6 @@ public Builder<S> unprocessedProperties(Map<String, Object> unprocessedPropertie

private final Object defaultValue;

private final Boolean nullable;

private final Boolean readOnly;

private final Boolean writeOnly;

private final Map<String, Object> unprocessedProperties;

/**
* Constructor.
*
Expand All @@ -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<String, Object> 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.
*
Expand Down Expand Up @@ -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() {
Expand All @@ -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 <S>
* the type of the schema being built by the builder subclass.
*/
public abstract static class Builder<S extends Schema> {

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<String, Object> unprocessedProperties = new HashMap<>(0);

public Builder<S> title(String title) {
this.title = title;
return this;
}

public Builder<S> description(String description) {
this.description = description;
return this;
}

public Builder<S> id(String id) {
this.id = id;
return this;
}

/**
* @deprecated Use {@link #schemaLocation(SchemaLocation)} instead.
*/
@Deprecated
public Builder<S> schemaLocation(String schemaLocation) {
return schemaLocation(SchemaLocation.parseURI(schemaLocation));
}

public Builder<S> schemaLocation(SchemaLocation location) {
this.schemaLocation = location;
return this;
}

public Builder<S> defaultValue(Object defaultValue) {
this.defaultValue = defaultValue;
return this;
}

public Builder<S> examples(List<String> examples) {
StringBuilder exampleBuilder = new StringBuilder("[");
for (String example : examples) {
exampleBuilder.append(example);
}
exampleBuilder.append("]");
this.examples = examples.toString();
return this;
}

public Builder<S> nullable(Boolean nullable) {
this.nullable = nullable;
return this;
}

public Builder<S> readOnly(Boolean readOnly) {
this.readOnly = readOnly;
return this;
}

public Builder<S> writeOnly(Boolean writeOnly) {
this.writeOnly = writeOnly;
return this;
}

public Builder<S> unprocessedProperties(Map<String, Object> unprocessedProperties) {
this.unprocessedProperties = unprocessedProperties;
return this;
}

public abstract S build();

}

public boolean hasDefaultValue() {
return this.defaultValue != null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 13 additions & 0 deletions core/src/main/java/org/everit/json/schema/loader/SchemaLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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<String> 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.
*
Expand Down