This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new e233402933 Updates to JsonSchema beans.
e233402933 is described below
commit e2334029337c7407275654d022a6c1191fa57bcd
Author: James Bognar <[email protected]>
AuthorDate: Sun Oct 12 16:35:24 2025 -0400
Updates to JsonSchema beans.
---
.../apache/juneau/bean/jsonschema/JsonSchema.java | 806 ++++++++++++++++++++-
.../juneau/bean/jsonschema/package-info.java | 190 ++++-
.../apache/juneau/bean/jsonschema/package2.html | 504 -------------
.../docs/topics/04.04.00.JuneauBeanJsonSchema.md | 451 +++++++++++-
.../juneau/bean/jsonschema/JsonSchema_Test.java | 221 +++---
5 files changed, 1508 insertions(+), 664 deletions(-)
diff --git
a/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/JsonSchema.java
b/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/JsonSchema.java
index c6ebf88743..12440e7781 100644
---
a/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/JsonSchema.java
+++
b/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/JsonSchema.java
@@ -32,38 +32,198 @@ import org.apache.juneau.swap.*;
/**
* Represents a top-level schema object bean in the JSON-Schema core
specification.
+ *
+ * <p>
+ * This implementation follows the JSON Schema Draft 2020-12 specification.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * <jc>// Create a simple schema for a person object</jc>
+ * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
+ * .setIdUri(<js>"https://example.com/person.schema.json"</js>)
+ *
.setSchemaVersionUri(<js>"https://json-schema.org/draft/2020-12/schema"</js>)
+ * .setTitle(<js>"Person"</js>)
+ * .setDescription(<js>"A person object"</js>)
+ * .setType(JsonType.<jsf>OBJECT</jsf>)
+ * .addProperties(
+ * <jk>new</jk> JsonSchemaProperty(<js>"firstName"</js>,
JsonType.<jsf>STRING</jsf>)
+ * .setMinLength(1)
+ * .setMaxLength(50),
+ * <jk>new</jk> JsonSchemaProperty(<js>"lastName"</js>,
JsonType.<jsf>STRING</jsf>)
+ * .setMinLength(1)
+ * .setMaxLength(50),
+ * <jk>new</jk> JsonSchemaProperty(<js>"age"</js>,
JsonType.<jsf>INTEGER</jsf>)
+ * .setMinimum(0)
+ * .setExclusiveMaximum(150)
+ * )
+ * .addRequired(<js>"firstName"</js>, <js>"lastName"</js>);
+ *
+ * <jc>// Serialize to JSON Schema</jc>
+ * String <jv>json</jv> =
JsonSerializer.<jsf>DEFAULT_SORTED</jsf>.serialize(<jv>schema</jv>);
+ * </p>
+ *
+ * <p>
+ * Output:
+ * <p class='bjson'>
+ * {
+ * <js>"$id"</js>:
<js>"https://example.com/person.schema.json"</js>,
+ * <js>"$schema"</js>:
<js>"https://json-schema.org/draft/2020-12/schema"</js>,
+ * <js>"title"</js>: <js>"Person"</js>,
+ * <js>"description"</js>: <js>"A person object"</js>,
+ * <js>"type"</js>: <js>"object"</js>,
+ * <js>"properties"</js>: {
+ * <js>"firstName"</js>: {
+ * <js>"type"</js>: <js>"string"</js>,
+ * <js>"minLength"</js>: 1,
+ * <js>"maxLength"</js>: 50
+ * },
+ * <js>"lastName"</js>: {
+ * <js>"type"</js>: <js>"string"</js>,
+ * <js>"minLength"</js>: 1,
+ * <js>"maxLength"</js>: 50
+ * },
+ * <js>"age"</js>: {
+ * <js>"type"</js>: <js>"integer"</js>,
+ * <js>"minimum"</js>: 0,
+ * <js>"exclusiveMaximum"</js>: 150
+ * }
+ * },
+ * <js>"required"</js>: [<js>"firstName"</js>, <js>"lastName"</js>]
+ * }
+ * </p>
+ *
+ * <h5 class='section'>Key Features:</h5>
+ * <ul class='spaced-list'>
+ * <li><b>Draft 2020-12 Support:</b> Includes all properties from the
latest JSON Schema specification
+ * <li><b>Backward Compatibility:</b> Deprecated Draft 04 properties (like
<c>id</c> and <c>definitions</c>) are still supported
+ * <li><b>Fluent API:</b> All setter methods return <c>this</c> for method
chaining
+ * <li><b>Type Safety:</b> Uses enums and typed collections for validation
+ * <li><b>Serialization:</b> Can be serialized to any format supported by
Juneau (JSON, XML, HTML, etc.)
+ * </ul>
+ *
+ * <h5 class='section'>Common Use Cases:</h5>
+ *
+ * <p><b>1. Simple Type Constraints:</b>
+ * <p class='bjava'>
+ * <jc>// String with length constraints</jc>
+ * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
+ * .setType(JsonType.<jsf>STRING</jsf>)
+ * .setMinLength(5)
+ * .setMaxLength(100)
+ * .setPattern(<js>"^[A-Za-z]+$"</js>);
+ * </p>
+ *
+ * <p><b>2. Numeric Ranges:</b>
+ * <p class='bjava'>
+ * <jc>// Number between 0 and 100 (exclusive)</jc>
+ * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
+ * .setType(JsonType.<jsf>NUMBER</jsf>)
+ * .setExclusiveMinimum(0)
+ * .setExclusiveMaximum(100)
+ * .setMultipleOf(0.5);
+ * </p>
+ *
+ * <p><b>3. Enumerations:</b>
+ * <p class='bjava'>
+ * <jc>// Status field with allowed values</jc>
+ * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
+ * .setType(JsonType.<jsf>STRING</jsf>)
+ * .addEnum(<js>"pending"</js>, <js>"active"</js>,
<js>"completed"</js>);
+ * </p>
+ *
+ * <p><b>4. Arrays:</b>
+ * <p class='bjava'>
+ * <jc>// Array of strings with constraints</jc>
+ * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
+ * .setType(JsonType.<jsf>ARRAY</jsf>)
+ * .setItems(<jk>new</jk>
JsonSchema().setType(JsonType.<jsf>STRING</jsf>))
+ * .setMinItems(1)
+ * .setMaxItems(10)
+ * .setUniqueItems(<jk>true</jk>);
+ * </p>
+ *
+ * <p><b>5. Conditional Schemas (Draft 07+):</b>
+ * <p class='bjava'>
+ * <jc>// Different validation based on country</jc>
+ * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
+ * .setType(JsonType.<jsf>OBJECT</jsf>)
+ * .addProperties(
+ * <jk>new</jk> JsonSchemaProperty(<js>"country"</js>,
JsonType.<jsf>STRING</jsf>),
+ * <jk>new</jk> JsonSchemaProperty(<js>"postalCode"</js>,
JsonType.<jsf>STRING</jsf>)
+ * )
+ * .setIf(<jk>new</jk> JsonSchema()
+ * .addProperties(<jk>new</jk>
JsonSchemaProperty(<js>"country"</js>).setConst(<js>"USA"</js>))
+ * )
+ * .setThen(<jk>new</jk> JsonSchema()
+ * .addProperties(<jk>new</jk>
JsonSchemaProperty(<js>"postalCode"</js>).setPattern(<js>"^[0-9]{5}$"</js>))
+ * );
+ * </p>
+ *
+ * <p><b>6. Reusable Definitions:</b>
+ * <p class='bjava'>
+ * <jc>// Schema with reusable components using $defs</jc>
+ * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
+ * .setType(JsonType.<jsf>OBJECT</jsf>)
+ * .addDef(<js>"address"</js>, <jk>new</jk> JsonSchema()
+ * .setType(JsonType.<jsf>OBJECT</jsf>)
+ * .addProperties(
+ * <jk>new</jk>
JsonSchemaProperty(<js>"street"</js>, JsonType.<jsf>STRING</jsf>),
+ * <jk>new</jk>
JsonSchemaProperty(<js>"city"</js>, JsonType.<jsf>STRING</jsf>)
+ * )
+ * )
+ * .addProperties(
+ * <jk>new</jk>
JsonSchemaProperty(<js>"billingAddress"</js>)
+ * .setRef(<js>"#/$defs/address"</js>),
+ * <jk>new</jk>
JsonSchemaProperty(<js>"shippingAddress"</js>)
+ * .setRef(<js>"#/$defs/address"</js>)
+ * );
+ * </p>
+ *
+ * <h5 class='section'>Migration from Draft 04:</h5>
+ * <ul class='spaced-list'>
+ * <li>Use {@link #setIdUri(Object)} instead of {@link #setId(Object)}
(deprecated)
+ * <li>Use {@link #setDefs(Map)} instead of {@link #setDefinitions(Map)}
(deprecated but still works)
+ * <li>Use {@link #setExclusiveMaximum(Number)} with a numeric value
instead of a boolean flag
+ * <li>Use {@link #setExclusiveMinimum(Number)} with a numeric value
instead of a boolean flag
+ * </ul>
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ * <li class='link'><a
href="https://json-schema.org/draft/2020-12/json-schema-core.html">JSON Schema
2020-12 Core</a>
+ * <li class='link'><a
href="https://json-schema.org/draft/2020-12/json-schema-validation.html">JSON
Schema 2020-12 Validation</a>
+ * <li class='link'><a class="doclink"
href="https://juneau.apache.org/docs/topics/JuneauBeanJsonSchema">juneau-bean-jsonschema</a>
+ * </ul>
*/
-@Bean(typeName="schema",
- properties="id,$schema,$ref,
title,description,type,definitions,properties,"
- +
"patternProperties,dependencies,items,multipleOf,maximum,exclusiveMaximum,"
- +
"minimum,exclusiveMinimum,maxLength,minLength,pattern,additionalItems,"
- +
"maxItems,minItems,uniqueItems,maxProperties,minProperties,required,"
- + "additionalProperties,enum,allOf,anyOf,oneOf,not"
-)
+@Bean(typeName="schema")
public class JsonSchema {
private String name; // Property
name. Not serialized.
- private URI id;
+ private URI idUri; // Draft
2020-12: $id
+ private URI id; // Draft 04: id
(deprecated but kept for compatibility)
private URI schemaVersion;
private String title;
private String description;
private JsonType typeJsonType; // JsonType
representation of type
private JsonTypeArray typeJsonTypeArray; // JsonTypeArray
representation of type
- private Map<String,JsonSchema> definitions;
+ private Map<String,JsonSchema> definitions; // Retained for
backward compatibility
+ private Map<String,JsonSchema> defs; // Draft
2020-12: $defs
private Map<String,JsonSchema> properties;
private Map<String,JsonSchema> patternProperties;
- private Map<String,JsonSchema> dependencies;
- private JsonSchema itemsSchema; //
JsonSchema representation of items
- private JsonSchemaArray itemsSchemaArray; //
JsonSchemaArray representation of items
+ private Map<String,JsonSchema> dependencies; // Retained for
backward compatibility
+ private Map<String,JsonSchema> dependentSchemas; // Draft 2019-09+
+ private Map<String,List<String>> dependentRequired; // Draft 2019-09+
+ private JsonSchema itemsSchema; // JsonSchema
representation of items
+ private JsonSchemaArray itemsSchemaArray; //
JsonSchemaArray representation of items
+ private JsonSchemaArray prefixItems; // Draft
2020-12: replaces tuple validation
private Number multipleOf;
private Number maximum;
- private Boolean exclusiveMaximum;
+ private Number exclusiveMaximum; // Draft 06+:
changed from Boolean to Number
private Number minimum;
- private Boolean exclusiveMinimum;
+ private Number exclusiveMinimum; // Draft 06+:
changed from Boolean to Number
private Integer maxLength;
private Integer minLength;
private String pattern;
private Boolean additionalItemsBoolean; // Boolean
representation of additionalItems
- private JsonSchemaArray additionalItemsSchemaArray; //
JsonSchemaArray representation of additionalItems
+ private JsonSchemaArray additionalItemsSchemaArray; //
JsonSchemaArray representation of additionalItems
+ private JsonSchema unevaluatedItems; // Draft 2019-09+
private Integer maxItems;
private Integer minItems;
private Boolean uniqueItems;
@@ -71,12 +231,22 @@ public class JsonSchema {
private Integer minProperties;
private List<String> required;
private Boolean additionalPropertiesBoolean; // Boolean
representation of additionalProperties
- private JsonSchema additionalPropertiesSchema; //
JsonSchema representation of additionalProperties
- private List<String> _enum; // NOSONAR - Intentional naming.
+ private JsonSchema additionalPropertiesSchema; // JsonSchema
representation of additionalProperties
+ private JsonSchema unevaluatedProperties; // Draft 2019-09+
+ private List<Object> _enum; // NOSONAR -
Intentional naming. Changed to Object to support any type
+ private Object _const; // NOSONAR -
Intentional naming. Draft 06+
+ private List<Object> examples; // Draft 06+
private List<JsonSchema> allOf;
private List<JsonSchema> anyOf;
private List<JsonSchema> oneOf;
private JsonSchema not;
+ private JsonSchema _if; // NOSONAR -
Intentional naming. Draft 07+
+ private JsonSchema _then; // NOSONAR -
Intentional naming. Draft 07+
+ private JsonSchema _else; // NOSONAR -
Intentional naming. Draft 07+
+ private Boolean readOnly; // Draft 07+
+ private Boolean writeOnly; // Draft 07+
+ private String contentMediaType; // Draft 07+
+ private String contentEncoding; // Draft 07+
private URI ref;
private JsonSchemaMap schemaMap;
private JsonSchema master = this;
@@ -94,8 +264,12 @@ public class JsonSchema {
/**
* Bean property getter: <property>name</property>.
*
+ * <p>
+ * This is an internal property used for tracking property names and is
not part of the JSON Schema specification.
+ *
* @return The value of the <property>name</property> property on this
bean, or <jk>null</jk> if it is not set.
*/
+ @BeanIgnore
public String getName() {
return name;
}
@@ -103,27 +277,76 @@ public class JsonSchema {
/**
* Bean property setter: <property>name</property>.
*
+ * <p>
+ * This is an internal property used for tracking property names and is
not part of the JSON Schema specification.
+ *
* @param name The new value for the <property>name</property> property
on this bean.
* @return This object.
*/
+ @BeanIgnore
public JsonSchema setName(String name) {
this.name = name;
return this;
}
+ /**
+ * Bean property getter: <property>$id</property>.
+ *
+ * <p>
+ * This is the Draft 2020-12 property for schema identification.
+ *
+ * @return The value of the <property>$id</property> property on this
bean, or <jk>null</jk> if it is not set.
+ */
+ @Beanp("$id")
+ public URI getIdUri() {
+ return idUri; // Return only idUri, not id (to avoid double
serialization)
+ }
+
+ /**
+ * Bean property setter: <property>$id</property>.
+ *
+ * <p>
+ * This is the Draft 2020-12 property for schema identification.
+ *
+ * <p>
+ * The value can be of any of the following types: {@link URI}, {@link
URL}, {@link String}.
+ * Strings must be valid URIs.
+ *
+ * <p>
+ * URIs defined by {@link UriResolver} can be used for values.
+ *
+ * @param idUri The new value for the <property>$id</property> property
on this bean.
+ * @return This object.
+ */
+ @Beanp("$id")
+ public JsonSchema setIdUri(Object idUri) {
+ this.idUri = toURI(idUri);
+ return this;
+ }
+
/**
* Bean property getter: <property>id</property>.
*
+ * <p>
+ * <b>Deprecated:</b> Use {@link #getIdUri()} instead.
+ * This property is retained for Draft 04 backward compatibility.
+ *
* @return The value of the <property>id</property> property on this
bean, or <jk>null</jk> if it is not set.
+ * @deprecated Use {@link #getIdUri()} instead.
*/
+ @Deprecated
public URI getId() {
- return id;
+ return id != null ? id : idUri; // Fall back to new '$id' for
compatibility when reading
}
/**
* Bean property setter: <property>id</property>.
*
* <p>
+ * <b>Deprecated:</b> Use {@link #setIdUri(Object)} instead.
+ * This property is retained for Draft 04 backward compatibility.
+ *
+ * <p>
* The value can be of any of the following types: {@link URI}, {@link
URL}, {@link String}.
* Strings must be valid URIs.
*
@@ -132,7 +355,9 @@ public class JsonSchema {
*
* @param id The new value for the <property>id</property> property on
this bean.
* @return This object.
+ * @deprecated Use {@link #setIdUri(Object)} instead.
*/
+ @Deprecated
public JsonSchema setId(Object id) {
this.id = toURI(id);
return this;
@@ -230,6 +455,7 @@ public class JsonSchema {
* @return
* The currently set value, or <jk>null</jk> if the property is
not set, or is set as a {@link JsonTypeArray}.
*/
+ @BeanIgnore
public JsonType getTypeAsJsonType() {
return typeJsonType;
}
@@ -242,6 +468,7 @@ public class JsonSchema {
*
* @return The currently set value, or <jk>null</jk> if the property is
not set, or is set as a {@link JsonType}.
*/
+ @BeanIgnore
public JsonTypeArray getTypeAsJsonTypeArray() {
return typeJsonTypeArray;
}
@@ -316,11 +543,15 @@ public class JsonSchema {
/**
* Bean property getter: <property>definitions</property>.
*
+ * <p>
+ * <b>Deprecated:</b> Use {@link #getDefs()} for Draft 2020-12
compliance.
+ * This property is retained for Draft 04 backward compatibility.
+ *
* @return
* The value of the <property>definitions</property> property on
this bean, or <jk>null</jk> if it is not set.
*/
public Map<String,JsonSchema> getDefinitions() {
- return definitions;
+ return definitions != null ? definitions : defs; // Fall back
to $defs for compatibility
}
/**
@@ -551,6 +782,7 @@ public class JsonSchema {
*
* @return The currently set value, or <jk>null</jk> if the property is
not set, or is set as a {@link JsonSchemaArray}.
*/
+ @BeanIgnore
public JsonSchema getItemsAsSchema() {
return itemsSchema;
}
@@ -563,6 +795,7 @@ public class JsonSchema {
*
* @return The currently set value, or <jk>null</jk> if the property is
not set, or is set as a {@link JsonSchema}.
*/
+ @BeanIgnore
public JsonSchemaArray getItemsAsSchemaArray() {
return itemsSchemaArray;
}
@@ -681,21 +914,29 @@ public class JsonSchema {
/**
* Bean property getter: <property>exclusiveMaximum</property>.
*
+ * <p>
+ * In Draft 06+, this is a numeric value representing the exclusive
upper bound.
+ * In Draft 04, this was a boolean flag. This implementation uses the
Draft 06+ semantics.
+ *
* @return
* The value of the <property>exclusiveMaximum</property> property
on this bean, or <jk>null</jk> if it is
* not set.
*/
- public Boolean isExclusiveMaximum() {
+ public Number getExclusiveMaximum() {
return exclusiveMaximum;
}
/**
* Bean property setter: <property>exclusiveMaximum</property>.
*
+ * <p>
+ * In Draft 06+, this is a numeric value representing the exclusive
upper bound.
+ * In Draft 04, this was a boolean flag. This implementation uses the
Draft 06+ semantics.
+ *
* @param exclusiveMaximum The new value for the
<property>exclusiveMaximum</property> property on this bean.
* @return This object.
*/
- public JsonSchema setExclusiveMaximum(Boolean exclusiveMaximum) {
+ public JsonSchema setExclusiveMaximum(Number exclusiveMaximum) {
this.exclusiveMaximum = exclusiveMaximum;
return this;
}
@@ -723,21 +964,29 @@ public class JsonSchema {
/**
* Bean property getter: <property>exclusiveMinimum</property>.
*
+ * <p>
+ * In Draft 06+, this is a numeric value representing the exclusive
lower bound.
+ * In Draft 04, this was a boolean flag. This implementation uses the
Draft 06+ semantics.
+ *
* @return
* The value of the <property>exclusiveMinimum</property> property
on this bean, or <jk>null</jk> if it is
* not set.
*/
- public Boolean isExclusiveMinimum() {
+ public Number getExclusiveMinimum() {
return exclusiveMinimum;
}
/**
* Bean property setter: <property>exclusiveMinimum</property>.
*
+ * <p>
+ * In Draft 06+, this is a numeric value representing the exclusive
lower bound.
+ * In Draft 04, this was a boolean flag. This implementation uses the
Draft 06+ semantics.
+ *
* @param exclusiveMinimum The new value for the
<property>exclusiveMinimum</property> property on this bean.
* @return This object.
*/
- public JsonSchema setExclusiveMinimum(Boolean exclusiveMinimum) {
+ public JsonSchema setExclusiveMinimum(Number exclusiveMinimum) {
this.exclusiveMinimum = exclusiveMinimum;
return this;
}
@@ -826,6 +1075,7 @@ public class JsonSchema {
*
* @return The currently set value, or <jk>null</jk> if the property is
not set, or is set as a {@link JsonSchemaArray}.
*/
+ @BeanIgnore
public Boolean getAdditionalItemsAsBoolean() {
return additionalItemsBoolean;
}
@@ -839,6 +1089,7 @@ public class JsonSchema {
*
* @return The currently set value, or <jk>null</jk> if the property is
not set, or is set as a {@link Boolean}.
*/
+ @BeanIgnore
public List<JsonSchema> getAdditionalItemsAsSchemaArray() {
return additionalItemsSchemaArray;
}
@@ -1102,6 +1353,7 @@ public class JsonSchema {
*
* @return The currently set value, or <jk>null</jk> if the property is
not set, or is set as a {@link JsonSchema}.
*/
+ @BeanIgnore
public Boolean getAdditionalPropertiesAsBoolean() {
return additionalPropertiesBoolean;
}
@@ -1115,6 +1367,7 @@ public class JsonSchema {
*
* @return The currently set value, or <jk>null</jk> if the property is
not set, or is set as a {@link Boolean}.
*/
+ @BeanIgnore
public JsonSchema getAdditionalPropertiesAsSchema() {
return additionalPropertiesSchema;
}
@@ -1182,7 +1435,7 @@ public class JsonSchema {
*
* @return The value of the <property>enum</property> property on this
bean, or <jk>null</jk> if it is not set.
*/
- public List<String> getEnum() {
+ public List<Object> getEnum() {
return _enum;
}
@@ -1192,7 +1445,7 @@ public class JsonSchema {
* @param _enum The new value for the <property>enum</property>
property on this bean.
* @return This object.
*/
- public JsonSchema setEnum(List<String> _enum) { // NOSONAR -
Intentional naming.
+ public JsonSchema setEnum(List<Object> _enum) { // NOSONAR -
Intentional naming.
this._enum = _enum;
return this;
}
@@ -1203,7 +1456,7 @@ public class JsonSchema {
* @param _enum The list of items to append to the
<property>enum</property> property on this bean.
* @return This object.
*/
- public JsonSchema addEnum(String..._enum) { // NOSONAR - Intentional
naming.
+ public JsonSchema addEnum(Object..._enum) { // NOSONAR - Intentional
naming.
if (this._enum == null)
this._enum = new LinkedList<>();
for (var e : _enum)
@@ -1337,6 +1590,488 @@ public class JsonSchema {
return this;
}
+ /**
+ * Bean property getter: <property>const</property>.
+ *
+ * <p>
+ * This property was added in Draft 06.
+ *
+ * @return The value of the <property>const</property> property on this
bean, or <jk>null</jk> if it is not set.
+ */
+ public Object getConst() {
+ return _const;
+ }
+
+ /**
+ * Bean property setter: <property>const</property>.
+ *
+ * <p>
+ * This property was added in Draft 06.
+ *
+ * @param _const The new value for the <property>const</property>
property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setConst(Object _const) { // NOSONAR - Intentional
naming.
+ this._const = _const;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>examples</property>.
+ *
+ * <p>
+ * This property was added in Draft 06.
+ *
+ * @return The value of the <property>examples</property> property on
this bean, or <jk>null</jk> if it is not set.
+ */
+ public List<Object> getExamples() {
+ return examples;
+ }
+
+ /**
+ * Bean property setter: <property>examples</property>.
+ *
+ * <p>
+ * This property was added in Draft 06.
+ *
+ * @param examples The new value for the <property>examples</property>
property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setExamples(List<Object> examples) {
+ this.examples = examples;
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>examples</property>.
+ *
+ * @param examples The list of items to append to the
<property>examples</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema addExamples(Object...examples) {
+ if (this.examples == null)
+ this.examples = new LinkedList<>();
+ for (var e : examples)
+ this.examples.add(e);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>if</property>.
+ *
+ * <p>
+ * This property was added in Draft 07 for conditional schema
application.
+ *
+ * @return The value of the <property>if</property> property on this
bean, or <jk>null</jk> if it is not set.
+ */
+ @Beanp("if")
+ public JsonSchema getIf() {
+ return _if;
+ }
+
+ /**
+ * Bean property setter: <property>if</property>.
+ *
+ * <p>
+ * This property was added in Draft 07 for conditional schema
application.
+ *
+ * @param _if The new value for the <property>if</property> property on
this bean.
+ * @return This object.
+ */
+ @Beanp("if")
+ public JsonSchema setIf(JsonSchema _if) { // NOSONAR - Intentional
naming.
+ this._if = _if;
+ setMasterOn(_if);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>then</property>.
+ *
+ * <p>
+ * This property was added in Draft 07 for conditional schema
application.
+ *
+ * @return The value of the <property>then</property> property on this
bean, or <jk>null</jk> if it is not set.
+ */
+ @Beanp("then")
+ public JsonSchema getThen() {
+ return _then;
+ }
+
+ /**
+ * Bean property setter: <property>then</property>.
+ *
+ * <p>
+ * This property was added in Draft 07 for conditional schema
application.
+ *
+ * @param _then The new value for the <property>then</property>
property on this bean.
+ * @return This object.
+ */
+ @Beanp("then")
+ public JsonSchema setThen(JsonSchema _then) { // NOSONAR - Intentional
naming.
+ this._then = _then;
+ setMasterOn(_then);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>else</property>.
+ *
+ * <p>
+ * This property was added in Draft 07 for conditional schema
application.
+ *
+ * @return The value of the <property>else</property> property on this
bean, or <jk>null</jk> if it is not set.
+ */
+ @Beanp("else")
+ public JsonSchema getElse() {
+ return _else;
+ }
+
+ /**
+ * Bean property setter: <property>else</property>.
+ *
+ * <p>
+ * This property was added in Draft 07 for conditional schema
application.
+ *
+ * @param _else The new value for the <property>else</property>
property on this bean.
+ * @return This object.
+ */
+ @Beanp("else")
+ public JsonSchema setElse(JsonSchema _else) { // NOSONAR - Intentional
naming.
+ this._else = _else;
+ setMasterOn(_else);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>readOnly</property>.
+ *
+ * <p>
+ * This property was added in Draft 07.
+ *
+ * @return The value of the <property>readOnly</property> property on
this bean, or <jk>null</jk> if it is not set.
+ */
+ public Boolean getReadOnly() {
+ return readOnly;
+ }
+
+ /**
+ * Bean property setter: <property>readOnly</property>.
+ *
+ * <p>
+ * This property was added in Draft 07.
+ *
+ * @param readOnly The new value for the <property>readOnly</property>
property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setReadOnly(Boolean readOnly) {
+ this.readOnly = readOnly;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>writeOnly</property>.
+ *
+ * <p>
+ * This property was added in Draft 07.
+ *
+ * @return The value of the <property>writeOnly</property> property on
this bean, or <jk>null</jk> if it is not set.
+ */
+ public Boolean getWriteOnly() {
+ return writeOnly;
+ }
+
+ /**
+ * Bean property setter: <property>writeOnly</property>.
+ *
+ * <p>
+ * This property was added in Draft 07.
+ *
+ * @param writeOnly The new value for the
<property>writeOnly</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setWriteOnly(Boolean writeOnly) {
+ this.writeOnly = writeOnly;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>contentMediaType</property>.
+ *
+ * <p>
+ * This property was added in Draft 07.
+ *
+ * @return The value of the <property>contentMediaType</property>
property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public String getContentMediaType() {
+ return contentMediaType;
+ }
+
+ /**
+ * Bean property setter: <property>contentMediaType</property>.
+ *
+ * <p>
+ * This property was added in Draft 07.
+ *
+ * @param contentMediaType The new value for the
<property>contentMediaType</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setContentMediaType(String contentMediaType) {
+ this.contentMediaType = contentMediaType;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>contentEncoding</property>.
+ *
+ * <p>
+ * This property was added in Draft 07.
+ *
+ * @return The value of the <property>contentEncoding</property>
property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public String getContentEncoding() {
+ return contentEncoding;
+ }
+
+ /**
+ * Bean property setter: <property>contentEncoding</property>.
+ *
+ * <p>
+ * This property was added in Draft 07.
+ *
+ * @param contentEncoding The new value for the
<property>contentEncoding</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setContentEncoding(String contentEncoding) {
+ this.contentEncoding = contentEncoding;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>$defs</property>.
+ *
+ * <p>
+ * This is the Draft 2020-12 replacement for
<property>definitions</property>.
+ * Both properties are supported for backward compatibility.
+ *
+ * @return The value of the <property>$defs</property> property on this
bean, or <jk>null</jk> if it is not set.
+ */
+ @Beanp("$defs")
+ public Map<String,JsonSchema> getDefs() {
+ return defs; // Return only defs, not definitions (to avoid
double serialization)
+ }
+
+ /**
+ * Bean property setter: <property>$defs</property>.
+ *
+ * <p>
+ * This is the Draft 2020-12 replacement for
<property>definitions</property>.
+ * Both properties are supported for backward compatibility.
+ *
+ * @param defs The new value for the <property>$defs</property>
property on this bean.
+ * @return This object.
+ */
+ @Beanp("$defs")
+ public JsonSchema setDefs(Map<String,JsonSchema> defs) {
+ this.defs = defs;
+ if (defs != null)
+ setMasterOn(defs.values());
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>$defs</property>.
+ *
+ * @param name The key in the defs map entry.
+ * @param def The value in the defs map entry.
+ * @return This object.
+ */
+ public JsonSchema addDef(String name, JsonSchema def) {
+ if (this.defs == null)
+ this.defs = map();
+ this.defs.put(name, def);
+ setMasterOn(def);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>prefixItems</property>.
+ *
+ * <p>
+ * This property was added in Draft 2020-12 for tuple validation.
+ *
+ * @return The value of the <property>prefixItems</property> property
on this bean, or <jk>null</jk> if it is not set.
+ */
+ public JsonSchemaArray getPrefixItems() {
+ return prefixItems;
+ }
+
+ /**
+ * Bean property setter: <property>prefixItems</property>.
+ *
+ * <p>
+ * This property was added in Draft 2020-12 for tuple validation.
+ *
+ * @param prefixItems The new value for the
<property>prefixItems</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setPrefixItems(JsonSchemaArray prefixItems) {
+ this.prefixItems = prefixItems;
+ setMasterOn(prefixItems);
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>prefixItems</property>.
+ *
+ * @param prefixItems The list of items to append to the
<property>prefixItems</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema addPrefixItems(JsonSchema...prefixItems) {
+ if (this.prefixItems == null)
+ this.prefixItems = new JsonSchemaArray();
+ this.prefixItems.addAll(prefixItems);
+ setMasterOn(prefixItems);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>unevaluatedItems</property>.
+ *
+ * <p>
+ * This property was added in Draft 2019-09.
+ *
+ * @return The value of the <property>unevaluatedItems</property>
property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public JsonSchema getUnevaluatedItems() {
+ return unevaluatedItems;
+ }
+
+ /**
+ * Bean property setter: <property>unevaluatedItems</property>.
+ *
+ * <p>
+ * This property was added in Draft 2019-09.
+ *
+ * @param unevaluatedItems The new value for the
<property>unevaluatedItems</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setUnevaluatedItems(JsonSchema unevaluatedItems) {
+ this.unevaluatedItems = unevaluatedItems;
+ setMasterOn(unevaluatedItems);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>unevaluatedProperties</property>.
+ *
+ * <p>
+ * This property was added in Draft 2019-09.
+ *
+ * @return The value of the <property>unevaluatedProperties</property>
property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public JsonSchema getUnevaluatedProperties() {
+ return unevaluatedProperties;
+ }
+
+ /**
+ * Bean property setter: <property>unevaluatedProperties</property>.
+ *
+ * <p>
+ * This property was added in Draft 2019-09.
+ *
+ * @param unevaluatedProperties The new value for the
<property>unevaluatedProperties</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setUnevaluatedProperties(JsonSchema
unevaluatedProperties) {
+ this.unevaluatedProperties = unevaluatedProperties;
+ setMasterOn(unevaluatedProperties);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>dependentSchemas</property>.
+ *
+ * <p>
+ * This property was added in Draft 2019-09 as a replacement for the
schema form of <property>dependencies</property>.
+ *
+ * @return The value of the <property>dependentSchemas</property>
property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Map<String,JsonSchema> getDependentSchemas() {
+ return dependentSchemas;
+ }
+
+ /**
+ * Bean property setter: <property>dependentSchemas</property>.
+ *
+ * <p>
+ * This property was added in Draft 2019-09 as a replacement for the
schema form of <property>dependencies</property>.
+ *
+ * @param dependentSchemas The new value for the
<property>dependentSchemas</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setDependentSchemas(Map<String,JsonSchema>
dependentSchemas) {
+ this.dependentSchemas = dependentSchemas;
+ if (dependentSchemas != null)
+ setMasterOn(dependentSchemas.values());
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>dependentSchemas</property>.
+ *
+ * @param name The key of the entry in the dependentSchemas map.
+ * @param schema The value of the entry in the dependentSchemas map.
+ * @return This object.
+ */
+ public JsonSchema addDependentSchema(String name, JsonSchema schema) {
+ if (this.dependentSchemas == null)
+ this.dependentSchemas = map();
+ this.dependentSchemas.put(name, schema);
+ setMasterOn(schema);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>dependentRequired</property>.
+ *
+ * <p>
+ * This property was added in Draft 2019-09 as a replacement for the
array form of <property>dependencies</property>.
+ *
+ * @return The value of the <property>dependentRequired</property>
property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Map<String,List<String>> getDependentRequired() {
+ return dependentRequired;
+ }
+
+ /**
+ * Bean property setter: <property>dependentRequired</property>.
+ *
+ * <p>
+ * This property was added in Draft 2019-09 as a replacement for the
array form of <property>dependencies</property>.
+ *
+ * @param dependentRequired The new value for the
<property>dependentRequired</property> property on this bean.
+ * @return This object.
+ */
+ public JsonSchema setDependentRequired(Map<String,List<String>>
dependentRequired) {
+ this.dependentRequired = dependentRequired;
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>dependentRequired</property>.
+ *
+ * @param name The key of the entry in the dependentRequired map.
+ * @param required The value of the entry in the dependentRequired map.
+ * @return This object.
+ */
+ public JsonSchema addDependentRequired(String name, List<String>
required) {
+ if (this.dependentRequired == null)
+ this.dependentRequired = map();
+ this.dependentRequired.put(name, required);
+ return this;
+ }
+
/**
* Bean property getter: <property>$ref</property>.
*
@@ -1400,20 +2135,30 @@ public class JsonSchema {
this.master = master;
if (definitions != null)
definitions.values().forEach(x -> x.setMaster(master));
+ if (defs != null)
+ defs.values().forEach(x -> x.setMaster(master));
if (properties != null)
properties.values().forEach(x -> x.setMaster(master));
if (patternProperties != null)
patternProperties.values().forEach(x ->
x.setMaster(master));
if (dependencies != null)
dependencies.values().forEach(x -> x.setMaster(master));
+ if (dependentSchemas != null)
+ dependentSchemas.values().forEach(x ->
x.setMaster(master));
if (itemsSchema != null)
itemsSchema.setMaster(master);
if (itemsSchemaArray != null)
itemsSchemaArray.forEach(x -> x.setMaster(master));
+ if (prefixItems != null)
+ prefixItems.forEach(x -> x.setMaster(master));
if (additionalItemsSchemaArray != null)
additionalItemsSchemaArray.forEach(x ->
x.setMaster(master));
+ if (unevaluatedItems != null)
+ unevaluatedItems.setMaster(master);
if (additionalPropertiesSchema != null)
additionalPropertiesSchema.setMaster(master);
+ if (unevaluatedProperties != null)
+ unevaluatedProperties.setMaster(master);
if (allOf != null)
allOf.forEach(x -> x.setMaster(master));
if (anyOf != null)
@@ -1422,6 +2167,12 @@ public class JsonSchema {
oneOf.forEach(x -> x.setMaster(master));
if (not != null)
not.setMaster(master);
+ if (_if != null)
+ _if.setMaster(master);
+ if (_then != null)
+ _then.setMaster(master);
+ if (_else != null)
+ _else.setMaster(master);
}
/**
@@ -1450,6 +2201,7 @@ public class JsonSchema {
* @param schemaMap The schema map to associate with this schema. Can
be <jk>null</jk>.
* @return This object.
*/
+ @BeanIgnore
public JsonSchema setSchemaMap(JsonSchemaMap schemaMap) {
this.schemaMap = schemaMap;
return this;
@@ -1457,6 +2209,6 @@ public class JsonSchema {
@Override /* Object */
public String toString() {
- return JsonSerializer.DEFAULT.toString(this);
+ return JsonSerializer.DEFAULT_SORTED.toString(this);
}
}
\ No newline at end of file
diff --git
a/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/package-info.java
b/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/package-info.java
index 6413ee9132..e32fb202fd 100644
---
a/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/package-info.java
+++
b/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/package-info.java
@@ -13,11 +13,193 @@
/**
* JSON Schema Data Transfer Objects
- *
+ *
+ * <h5 class='topic'>Overview</h5>
+ *
+ * <p>
+ * Juneau supports serializing and parsing of JSON Schema documents through
the use of beans defined in the
+ * <c>org.apache.juneau.bean.jsonschema</c> package.
+ * These beans are used with the existing {@link
org.apache.juneau.json.JsonSerializer} and
+ * {@link org.apache.juneau.json.JsonParser} classes to produce and consume
JSON Schema documents.
+ * </p>
+ *
+ * <p>
+ * <b>NOTE:</b> This implementation follows the JSON Schema Draft 2020-12
specification.
+ * For backward compatibility, deprecated properties from earlier drafts
(Draft 04) are still supported.
+ * </p>
+ *
+ * <h5 class='topic'>Bean Classes</h5>
+ *
+ * <p>
+ * The bean classes that make up the model are as follows:
+ * </p>
+ * <ul class='spaced-list'>
+ * <li>{@link org.apache.juneau.bean.jsonschema.JsonSchema} - Top level
schema object.
+ * <li>{@link org.apache.juneau.bean.jsonschema.JsonSchemaProperty} - A
subclass of <c>JsonSchema</c> for
+ * representing properties.
+ * <li>{@link
org.apache.juneau.bean.jsonschema.JsonSchemaPropertySimpleArray} - A
convenience subclass of
+ * <c>JsonSchemaProperty</c> for representing properties of simple
array types.
+ * <li>{@link org.apache.juneau.bean.jsonschema.JsonSchemaRef} -
Represents a URI reference to another schema.
+ * <li>{@link org.apache.juneau.bean.jsonschema.JsonSchemaArray} - An
array of <c>JsonSchema</c> objects.
+ * <li>{@link org.apache.juneau.bean.jsonschema.JsonType} - An enum of
possible JSON data types.
+ * <li>{@link org.apache.juneau.bean.jsonschema.JsonTypeArray} - An array
of <c>JsonType</c> objects.
+ * </ul>
+ *
+ * <h5 class='topic'>Creating JSON Schema Documents</h5>
+ *
+ * <p>
+ * JSON Schema documents can be constructed using the Juneau JSON Schema beans
as a document model object.
+ * These beans are defined with fluent-style setters to make constructing
documents as easy as possible.
+ * </p>
+ *
+ * <p>
+ * The following is an example JSON Schema document:
+ * </p>
+ * <p class='bjson'>
+ * {
+ * <js>"title"</js>: <js>"Example Schema"</js>,
+ * <js>"type"</js>: <js>"object"</js>,
+ * <js>"properties"</js>: {
+ * <js>"firstName"</js>: {
+ * <js>"type"</js>: <js>"string"</js>
+ * },
+ * <js>"lastName"</js>: {
+ * <js>"type"</js>: <js>"string"</js>
+ * },
+ * <js>"age"</js>: {
+ * <js>"description"</js>: <js>"Age in years"</js>,
+ * <js>"type"</js>: <js>"integer"</js>,
+ * <js>"minimum"</js>: 0
+ * }
+ * },
+ * <js>"required"</js>: [<js>"firstName"</js>, <js>"lastName"</js>]
+ * }
+ * </p>
+ *
+ * <p>
+ * This document can be constructed using the following code:
+ * </p>
+ * <p class='bjava'>
+ * <jc>// Create the document object model</jc>
+ * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
+ * .setTitle(<js>"Example Schema"</js>)
+ * .setType(JsonType.<jsf>OBJECT</jsf>)
+ * .addProperties(
+ * <jk>new</jk> JsonSchemaProperty(<js>"firstName"</js>,
JsonType.<jsf>STRING</jsf>),
+ * <jk>new</jk> JsonSchemaProperty(<js>"lastName"</js>,
JsonType.<jsf>STRING</jsf>),
+ * <jk>new</jk> JsonSchemaProperty(<js>"age"</js>,
JsonType.<jsf>INTEGER</jsf>)
+ * .setDescription(<js>"Age in years"</js>)
+ * .setMinimum(0)
+ * )
+ * .addRequired(<js>"firstName"</js>, <js>"lastName"</js>);
+ *
+ * <jc>// Serialize to JSON</jc>
+ * String <jv>json</jv> =
JsonSerializer.<jsf>DEFAULT_READABLE</jsf>.serialize(<jv>schema</jv>);
+ * </p>
+ *
+ * <p>
+ * The following is a more-complex example showing various kinds of
constraints:
+ * </p>
+ * <p class='bjson'>
+ * {
+ * <js>"$id"</js>:
<js>"http://some.site.somewhere/entry-schema#"</js>,
+ * <js>"$schema"</js>:
<js>"https://json-schema.org/draft/2020-12/schema"</js>,
+ * <js>"description"</js>: <js>"schema for an fstab entry"</js>,
+ * <js>"type"</js>: <js>"object"</js>,
+ * <js>"required"</js>: [ <js>"storage"</js> ],
+ * <js>"properties"</js>: {
+ * <js>"storage"</js>: {
+ * <js>"type"</js>: <js>"object"</js>,
+ * <js>"oneOf"</js>: [
+ * { <js>"$ref"</js>:
<js>"#/definitions/diskDevice"</js> },
+ * { <js>"$ref"</js>:
<js>"#/definitions/diskUUID"</js> },
+ * { <js>"$ref"</js>:
<js>"#/definitions/nfs"</js> },
+ * { <js>"$ref"</js>:
<js>"#/definitions/tmpfs"</js> }
+ * ]
+ * },
+ * <js>"fstype"</js>: {
+ * <js>"enum"</js>: [ <js>"ext3"</js>,
<js>"ext4"</js>, <js>"btrfs"</js> ]
+ * },
+ * <js>"options"</js>: {
+ * <js>"type"</js>: <js>"array"</js>,
+ * <js>"minItems"</js>: 1,
+ * <js>"items"</js>: { <js>"type"</js>:
<js>"string"</js> },
+ * <js>"uniqueItems"</js>: <jk>true</jk>
+ * },
+ * <js>"readonly"</js>: { <js>"type"</js>:
<js>"boolean"</js> }
+ * },
+ * <js>"definitions"</js>: {
+ * <js>"diskDevice"</js>: {},
+ * <js>"diskUUID"</js>: {},
+ * <js>"nfs"</js>: {},
+ * <js>"tmpfs"</js>: {}
+ * }
+ * }
+ * </p>
+ *
+ * <p>
+ * This document can be constructed using the following code:
+ * </p>
+ * <p class='bjava'>
+ * JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
+ * .setIdUri(<js>"http://some.site.somewhere/entry-schema#"</js>)
+ *
.setSchemaVersionUri(<js>"https://json-schema.org/draft/2020-12/schema"</js>)
+ * .setDescription(<js>"schema for an fstab entry"</js>)
+ * .setType(JsonType.<jsf>OBJECT</jsf>)
+ * .addRequired(<js>"storage"</js>)
+ * .addProperties(
+ * <jk>new</jk> JsonSchemaProperty(<js>"storage"</js>)
+ * .setType(JsonType.<jsf>OBJECT</jsf>)
+ * .addOneOf(
+ * <jk>new</jk>
JsonSchemaRef(<js>"#/definitions/diskDevice"</js>),
+ * <jk>new</jk>
JsonSchemaRef(<js>"#/definitions/diskUUID"</js>),
+ * <jk>new</jk>
JsonSchemaRef(<js>"#/definitions/nsf"</js>),
+ * <jk>new</jk>
JsonSchemaRef(<js>"#/definitions/tmpfs"</js>)
+ * ),
+ * <jk>new</jk> JsonSchemaProperty(<js>"fstype"</js>)
+ * .addEnum(<js>"ext3"</js>, <js>"ext4"</js>,
<js>"btrfs"</js>),
+ * <jk>new</jk>
JsonSchemaPropertySimpleArray(<js>"options"</js>, JsonType.<jsf>STRING</jsf>)
+ * .setMinItems(1)
+ * .setUniqueItems(<jk>true</jk>),
+ * <jk>new</jk> JsonSchemaProperty(<js>"readonly"</js>)
+ * .setType(JsonType.<jsf>BOOLEAN</jsf>)
+ * )
+ * .addDefinition(<js>"diskDevice"</js>, <jk>new</jk> JsonSchema())
+ * .addDefinition(<js>"diskUUID"</js>, <jk>new</jk> JsonSchema())
+ * .addDefinition(<js>"nfs"</js>, <jk>new</jk> JsonSchema())
+ * .addDefinition(<js>"tmpfs"</js>, <jk>new</jk> JsonSchema());
+ *
+ * <jc>// Serialize to JSON</jc>
+ * String <jv>json</jv> =
JsonSerializer.<jsf>DEFAULT_READABLE</jsf>.serialize(<jv>schema</jv>);
+ * </p>
+ *
+ * <h5 class='topic'>Serializing to Other Data Types</h5>
+ *
+ * <p>
+ * Since the JSON Schema DTOs are simple beans, they can be used to serialize
to a variety of other
+ * language types as well as JSON.
+ * This also allows JSON Schema documents to be easily served up using the
Juneau REST API.
+ * </p>
+ *
+ * <h5 class='topic'>Parsing JSON Schema Documents</h5>
+ *
* <p>
- * This package contains predefined DTOs for working with JSON Schema
definitions.
- * These classes provide a convenient way to serialize and parse JSON Schema
content
- * using Juneau's marshalling framework.
+ * Use the {@link org.apache.juneau.json.JsonParser} to parse JSON Schema
documents into DTOs:
* </p>
+ * <p class='bjava'>
+ * <jc>// Use parser to load JSON Schema document into JSON Schema
DTOs</jc>
+ * JsonSchema <jv>schema</jv> =
JsonParser.<jsf>DEFAULT</jsf>.parse(<jv>json</jv>, JsonSchema.<jk>class</jk>);
+ * </p>
+ *
+ * <p>
+ * Schema objects can also be constructed from other media types using the
appropriate parsers.
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul>
+ * <li class='link'><a
href="https://json-schema.org/draft/2020-12/json-schema-core.html">JSON Schema
2020-12 Core</a>
+ * <li class='link'><a
href="https://json-schema.org/draft/2020-12/json-schema-validation.html">JSON
Schema 2020-12 Validation</a>
+ * <li class='link'><a class="doclink"
href="https://juneau.apache.org/docs/topics/JuneauBeanJsonSchema">juneau-bean-jsonschema</a>
+ * </ul>
*/
package org.apache.juneau.bean.jsonschema;
diff --git
a/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/package2.html
b/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/package2.html
deleted file mode 100644
index adcd01d277..0000000000
---
a/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/package2.html
+++ /dev/null
@@ -1,504 +0,0 @@
-<!DOCTYPE HTML>
-<!--
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file
- * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- *
-
***************************************************************************************************************************/
--->
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <style type="text/css">
- /* For viewing in Page Designer */
- @IMPORT url("../../../../../../../javadoc.css");
-
- /* For viewing in REST interface */
- @IMPORT url("../htdocs/javadoc.css");
- body {
- margin: 20px;
- }
- </style>
-</head>
-<body>
-<p>JSON-Schema Data Transfer Objects</p>
-
-<!--
========================================================================================================
-->
-<a id="Overview"></a>
-<h2 class='topic'>1 - Overview</h2>
-<div class='topic'>
- <p>
- Juneau supports serializing and parsing of JSON-Schema
documents through the use of beans defined in the
- <code>org.apache.juneau.bean.jsonschema</code> package.
- <br>These beans are used with the existing {@link
org.apache.juneau.json.JsonSerializer} and
- {@link org.apache.juneau.json.JsonParser} classes to produce
and consume JSON-Schema documents.
- </p>
- <p>
- <b>NOTE:</b> JSON-Schema is currently in draft form.
- This API may change as the JSON-Schema specification changes.
- </p>
-
- <!--
========================================================================================================
-->
- <a id="SchemaDefinition"></a>
- <h3 class='topic'>1.1 - JSON-Schema schema definition</h3>
- <div class='topic'>
- <p>
- The draft JSON-Schema specification that the
JSON-Schema beans are modeled after is as follows:
- </p>
- <p class='bjson'>
- {
- <js>"id"</js>:
<js>"http://json-schema.org/draft-04/schema#"</js>,
- <js>"$schema"</js>:
<js>"http://json-schema.org/draft-04/schema#"</js>,
- <js>"description"</js>: <js>"Core schema meta-schema"</js>,
- <js>"definitions"</js>: {
- <js>"schemaArray"</js>: {
- <js>"type"</js>: <js>"array"</js>,
- <js>"minItems"</js>: 1,
- <js>"items"</js>: { <js>"$ref"</js>:
<js>"#"</js> }
- },
- <js>"positiveInteger"</js>: {
- <js>"type"</js>: <js>"integer"</js>,
- <js>"minimum"</js>: 0
- },
- <js>"positiveIntegerDefault0"</js>: {
- <js>"allOf"</js>: [ { <js>"$ref"</js>:
<js>"#/definitions/positiveInteger"</js> },
- { <js>"default"</js>: 0 } ]
- },
- <js>"simpleTypes"</js>: {
- <js>"enum"</js>: [ <js>"array"</js>,
<js>"boolean"</js>, <js>"integer"</js>, <js>"null"</js>,
- <js>"number"</js>, <js>"object"</js>,
<js>"string"</js> ]
- },
- <js>"stringArray"</js>: {
- <js>"type"</js>: <js>"array"</js>,
- <js>"items"</js>: { <js>"type"</js>:
<js>"string"</js> },
- <js>"minItems"</js>: 1,
- <js>"uniqueItems"</js>: <jk>true</jk>
- }
- },
- <js>"type"</js>: <js>"object"</js>,
- <js>"properties"</js>: {
- <js>"id"</js>: {
- <js>"type"</js>: <js>"string"</js>,
- <js>"format"</js>: <js>"uri"</js>
- },
- <js>"$schema"</js>: {
- <js>"type"</js>: <js>"string"</js>,
- <js>"format"</js>: <js>"uri"</js>
- },
- <js>"title"</js>: {
- <js>"type"</js>: <js>"string"</js>
- },
- <js>"description"</js>: {
- <js>"type"</js>: <js>"string"</js>
- },
- <js>"default"</js>: {},
- <js>"multipleOf"</js>: {
- <js>"type"</js>: <js>"number"</js>,
- <js>"minimum"</js>: 0,
- <js>"exclusiveMinimum"</js>: <jk>true</jk>
- },
- <js>"maximum"</js>: {
- <js>"type"</js>: <js>"number"</js>
- },
- <js>"exclusiveMaximum"</js>: {
- <js>"type"</js>: <js>"boolean"</js>,
- <js>"default"</js>: <jk>false</jk>
- },
- <js>"minimum"</js>: {
- <js>"type"</js>: <js>"number"</js>
- },
- <js>"exclusiveMinimum"</js>: {
- <js>"type"</js>: <js>"boolean"</js>,
- <js>"default"</js>: <jk>false</jk>
- },
- <js>"maxLength"</js>: { <js>"$ref"</js>:
<js>"#/definitions/positiveInteger"</js> },
- <js>"minLength"</js>: { <js>"$ref"</js>:
<js>"#/definitions/positiveIntegerDefault0"</js> },
- <js>"pattern"</js>: {
- <js>"type"</js>: <js>"string"</js>,
- <js>"format"</js>: <js>"regex"</js>
- },
- <js>"additionalItems"</js>: {
- <js>"anyOf"</js>: [
- { <js>"type"</js>: <js>"boolean"</js> },
- { <js>"$ref"</js>: <js>"#"</js> }
- ],
- <js>"default"</js>: {}
- },
- <js>"items"</js>: {
- <js>"anyOf"</js>: [
- { <js>"$ref"</js>: <js>"#"</js> },
- { <js>"$ref"</js>:
<js>"#/definitions/schemaArray"</js> }
- ],
- <js>"default"</js>: {}
- },
- <js>"maxItems"</js>: { <js>"$ref"</js>:
<js>"#/definitions/positiveInteger"</js> },
- <js>"minItems"</js>: { <js>"$ref"</js>:
<js>"#/definitions/positiveIntegerDefault0"</js> },
- <js>"uniqueItems"</js>: {
- <js>"type"</js>: <js>"boolean"</js>,
- <js>"default"</js>: <jk>false</jk>
- },
- <js>"maxProperties"</js>: { <js>"$ref"</js>:
<js>"#/definitions/positiveInteger"</js> },
- <js>"minProperties"</js>: { <js>"$ref"</js>:
<js>"#/definitions/positiveIntegerDefault0"</js> },
- <js>"required"</js>: { <js>"$ref"</js>:
<js>"#/definitions/stringArray"</js> },
- <js>"additionalProperties"</js>: {
- <js>"anyOf"</js>: [
- { <js>"type"</js>: <js>"boolean"</js> },
- { <js>"$ref"</js>: <js>"#"</js> }
- ],
- <js>"default"</js>: {}
- },
- <js>"definitions"</js>: {
- <js>"type"</js>: <js>"object"</js>,
- <js>"additionalProperties"</js>: {
<js>"$ref"</js>: <js>"#"</js> },
- <js>"default"</js>: {}
- },
- <js>"properties"</js>: {
- <js>"type"</js>: <js>"object"</js>,
- <js>"additionalProperties"</js>: {
<js>"$ref"</js>: <js>"#"</js> },
- <js>"default"</js>: {}
- },
- <js>"patternProperties"</js>: {
- <js>"type"</js>: <js>"object"</js>,
- <js>"additionalProperties"</js>: {
<js>"$ref"</js>: <js>"#"</js> },
- <js>"default"</js>: {}
- },
- <js>"dependencies"</js>: {
- <js>"type"</js>: <js>"object"</js>,
- <js>"additionalProperties"</js>: {
- <js>"anyOf"</js>: [
- { <js>"$ref"</js>: <js>"#"</js>
},
- { <js>"$ref"</js>:
<js>"#/definitions/stringArray"</js> }
- ]
- }
- },
- <js>"enum"</js>: {
- <js>"type"</js>: <js>"array"</js>,
- <js>"minItems"</js>: 1,
- <js>"uniqueItems"</js>: <jk>true</jk>
- },
- <js>"type"</js>: {
- <js>"anyOf"</js>: [
- { <js>"$ref"</js>:
<js>"#/definitions/simpleTypes"</js> },
- {
- <js>"type"</js>:
<js>"array"</js>,
- <js>"items"</js>: {
<js>"$ref"</js>: <js>"#/definitions/simpleTypes"</js> },
- <js>"minItems"</js>: 1,
- <js>"uniqueItems"</js>:
<jk>true</jk>
- }
- ]
- },
- <js>"allOf"</js>: { <js>"$ref"</js>:
<js>"#/definitions/schemaArray"</js> },
- <js>"anyOf"</js>: { <js>"$ref"</js>:
<js>"#/definitions/schemaArray"</js> },
- <js>"oneOf"</js>: { <js>"$ref"</js>:
<js>"#/definitions/schemaArray"</js> },
- <js>"not"</js>: { <js>"$ref"</js>: <js>"#"</js> }
- },
- <js>"dependencies"</js>: {
- <js>"exclusiveMaximum"</js>: [ <js>"maximum"</js> ],
- <js>"exclusiveMinimum"</js>: [ <js>"minimum"</js> ]
- },
- <js>"default"</js>: {}
- }
- </p>
- <p>
- The bean classes that make up the model are as follows:
- </p>
- <ul class='spaced-list'>
- <li>
- {@link
org.apache.juneau.bean.jsonschema.JsonSchema} - Top level schema object.
- <li>
- {@link
org.apache.juneau.bean.jsonschema.JsonSchemaProperty} - A subclass of
<code>Schema</code> for
- representing properties.
- <li>
- {@link
org.apache.juneau.bean.jsonschema.JsonSchemaPropertySimpleArray} - A
convenience subclass of
- <code>SchemaProperty</code> for representing
properties of simple array types.
- <li>
- {@link
org.apache.juneau.bean.jsonschema.JsonSchemaRef} - Represents a URI reference
to another schema.
- <li>
- {@link
org.apache.juneau.bean.jsonschema.JsonSchemaArray} - An array of
<code>Schema</code> objects.
- <li>
- {@link
org.apache.juneau.bean.jsonschema.JsonType} - An enum of possible JSON data
types.
- <li>
- {@link
org.apache.juneau.bean.jsonschema.JsonTypeArray} - An array of
<code>JsonType</code> objects.
- </ul>
- </div>
-
-
- <!--
========================================================================================================
-->
- <a id="Serialize"></a>
- <h3 class='topic'>1.2 - Creating JSON-Schema documents</h3>
- <div class='topic'>
- <p>
- JSON-Schema documents can be constructed using the
Juneau JSON-Schema beans as a document model object.
- These beans are defined with fluent-style setters to
make constructing documents as easy as possible.
- </p>
- <p>
- The following is an example JSON-Schema document:
- </p>
- <p class='bjson'>
- {
- <js>"title"</js>: <js>"Example Schema"</js>,
- <js>"type"</js>: <js>"object"</js>,
- <js>"properties"</js>: {
- <js>"firstName"</js>: {
- <js>"type"</js>: <js>"string"</js>
- },
- <js>"lastName"</js>: {
- <js>"type"</js>: <js>"string"</js>
- },
- <js>"age"</js>: {
- <js>"description"</js>: <js>"Age in years"</js>,
- <js>"type"</js>: <js>"integer"</js>,
- <js>"minimum"</js>: 0
- }
- },
- <js>"required"</js>: [<js>"firstName"</js>, <js>"lastName"</js>]
- }
- </p>
- <p>
- This document can be constructing using the following
code:
- </p>
- <p class='bjava'>
- <jc>// Create the document object model</jc>
- JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
- .setTitle(<js>"Example Schema"</js>)
- .setType(JsonType.<jsf>OBJECT</jsf>)
- .addProperties(
- <jk>new</jk> JsonSchemaProperty(<js>"firstName"</js>,
JsonType.<jsf>STRING</jsf>),
- <jk>new</jk> JsonSchemaProperty(<js>"lastName"</js>,
JsonType.<jsf>STRING</jsf>),
- <jk>new</jk> JsonSchemaProperty(<js>"age"</js>,
JsonType.<jsf>INTEGER</jsf>)
- .setDescription(<js>"Age in years"</js>)
- .setMinimum(0)
- )
- .addRequired(<js>"firstName"</js>, <js>"lastName"</js>);
-
- <jc>// Serialize to JSON</jc>
- String <jv>json</jv> =
JsonSerializer.<jsf>DEFAULT_READABLE</jsf>.serialize(<jv>schema</jv>);
- </p>
- <p>
- The following is a more-complex example showing various
kinds of constraints.
- </p>
- <p class='bjson'>
- {
- <js>"id"</js>:
<js>"http://some.site.somewhere/entry-schema#"</js>,
- <js>"$schema"</js>:
<js>"http://json-schema.org/draft-04/schema#"</js>,
- <js>"description"</js>: <js>"schema for an fstab entry"</js>,
- <js>"type"</js>: <js>"object"</js>,
- <js>"required"</js>: [ <js>"storage"</js> ],
- <js>"properties"</js>: {
- <js>"storage"</js>: {
- <js>"type"</js>: <js>"object"</js>,
- <js>"oneOf"</js>: [
- { <js>"$ref"</js>:
<js>"#/definitions/diskDevice"</js> },
- { <js>"$ref"</js>:
<js>"#/definitions/diskUUID"</js> },
- { <js>"$ref"</js>:
<js>"#/definitions/nfs"</js> },
- { <js>"$ref"</js>:
<js>"#/definitions/tmpfs"</js> }
- ]
- },
- <js>"fstype"</js>: {
- <js>"enum"</js>: [ <js>"ext3"</js>,
<js>"ext4"</js>, <js>"btrfs"</js> ]
- },
- <js>"options"</js>: {
- <js>"type"</js>: <js>"array"</js>,
- <js>"minItems"</js>: 1,
- <js>"items"</js>: { <js>"type"</js>:
<js>"string"</js> },
- <js>"uniqueItems"</js>: <jk>true</jk>
- },
- <js>"readonly"</js>: { <js>"type"</js>:
<js>"boolean"</js> }
- },
- <js>"definitions"</js>: {
- <js>"diskDevice"</js>: {},
- <js>"diskUUID"</js>: {},
- <js>"nfs"</js>: {},
- <js>"tmpfs"</js>: {}
- }
- }
- </p>
- <p>
- This document can be constructing using the following
code:
- </p>
- <p class='bjava'>
- JsonSchema <jv>schema</jv> = <jk>new</jk> JsonSchema()
- .setId(<js>"http://some.site.somewhere/entry-schema#"</js>)
-
.setSchemaVersionId(<js>"http://json-schema.org/draft-04/schema#"</js>)
- .setDescription(<js>"schema for an fstab entry"</js>)
- .setType(JsonType.<jsf>OBJECT</jsf>)
- .addRequired(<js>"storage"</js>)
- .addProperties(
- <jk>new</jk> JsonSchemaProperty(<js>"storage"</js>)
- .setType(JsonType.<jsf>OBJECT</jsf>)
- .addOneOf(
- <jk>new</jk>
JsonSchemaRef(<js>"#/definitions/diskDevice"</js>),
- <jk>new</jk>
JsonSchemaRef(<js>"#/definitions/diskUUID"</js>),
- <jk>new</jk>
JsonSchemaRef(<js>"#/definitions/nsf"</js>),
- <jk>new</jk>
JsonSchemaRef(<js>"#/definitions/tmpfs"</js>)
- ),
- <jk>new</jk> JsonSchemaProperty(<js>"fstype"</js>)
- .addEnum(<js>"ext3"</js>, <js>"ext4"</js>,
<js>"btrfs"</js>),
- <jk>new</jk>
JsonSchemaPropertySimpleArray(<js>"options"</js>, JsonType.<jsf>STRING</jsf>)
- .setMinItems(1)
- .setUniqueItems(<jk>true</jk>),
- <jk>new</jk> JsonSchemaProperty(<js>"readonly"</js>)
- .setType(JsonType.<jsf>BOOLEAN</jsf>)
- )
- .addDefinition(<js>"diskDevice"</js>,
- <jk>new</jk> JsonSchema()
- )
- .addDefinition(<js>"diskUUID"</js>,
- <jk>new</jk> JsonSchema()
- )
- .addDefinition(<js>"nfs"</js>,
- <jk>new</jk> JsonSchema()
- )
- .addDefinition(<js>"tmpfs"</js>,
- <jk>new</jk> JsonSchema()
- );
-
- <jc>// Serialize to JSON</jc>
- String <jv>json</jv> =
JsonSerializer.<jsf>DEFAULT_READABLE</jsf>.serialize(<jv>schema</jv>);
- </p>
-
-
- <!--
========================================================================================================
-->
- <a id="SerializeToOther"></a>
- <h4 class='topic'>1.2.1 - Serializing to other data types</h4>
- <div class='topic'>
- <p>
- Since the JSON-Schema DTOs are simple beans,
they can be used to serialize to a variety of other
- language types as well as JSON.
- This also allows JSON-Schema documents to be
easily served up using the Juneau REST API.
- </p>
- <p>
- The sample web application includes a REST
resource that generates a JSON-Schema document.
- We'll use this resource to show what the
JSON-Schema document looks like in other languages.
- </p>
- <p class='bjava'>
- <jd>/**
- * Sample resource that shows how to serialize JSON-Schema documents.
- */</jd>
- <ja>@Rest</ja>(
- path=<js>"/jsonSchema"</js>,
- messages=<js>"nls/JsonSchemaResource"</js>,
- title=<js>"Sample JSON-Schema document"</js>
- )
- <ja>@HtmlDocConfig</ja>(
- navlinks={
- <js>"options: ?method=OPTIONS"</js>
- }
- )
- <jk>public class</jk> JsonSchemaResource <jk>extends</jk>
BasicRestServlet {
-
- <jk>private</jk> JsonSchema <jf>schema</jf>; <jc>// The
schema document</jc>
-
- <jd>/** Servlet initialization */</jd>
- <ja>@Override</ja>
- <jk>public void</jk> init() {
-
- <jk>try</jk> {
- <jf>schema</jf> = <jk>new</jk> JsonSchema()
-
.setId(<js>"http://example.com/sample-schema#"</js>)
-
.setSchemaVersionUri(<js>"http://json-schema.org/draft-04/schema#"</js>)
- .setTitle(<js>"Example Schema"</js>)
- .setType(JsonType.<jsf>OBJECT</jsf>)
- .addProperties(
- <jk>new</jk>
JsonSchemaProperty(<js>"firstName"</js>, JsonType.<jsf>STRING</jsf>),
- <jk>new</jk>
JsonSchemaProperty(<js>"lastName"</js>, JsonType.<jsf>STRING</jsf>),
- <jk>new</jk>
JsonSchemaProperty(<js>"age"</js>, JsonType.<jsf>INTEGER</jsf>)
-
.setDescription(<js>"Age in years"</js>)
- .setMinimum(0)
- )
- .addRequired(<js>"firstName"</js>,
<js>"lastName"</js>);
- } <jk>catch</jk> (Exception <jv>e</jv>) {
- <jk>throw new</jk> RuntimeException(<jv>e</jv>);
- }
- }
-
- <jd>/** GET request handler */</jd>
- <ja>@RestGet</ja>(<js>"/"</js>)
- <jk>public</jk> JsonSchema getSchema() <jk>throws</jk>
Exception {
- <jk>return</jk> <jf>schema</jf>;
- }
-
- <jd>/**
- * PUT request handler.
- * Replaces the schema document with the specified content, and
then mirrors it as the response.
- */</jd>
- <ja>@RestPut</ja>(<js>"/"</js>)
- <jk>public</jk> JsonSchema setSchema(<ja>@Content</ja>
JsonSchema <jv>schema</jv>) <jk>throws</jk> Exception {
- <jk>this</jk>.<jf>schema</jf> = <jv>schema</jv>;
- <jk>return</jk> <jk>this</jk>.<jf>schema</jf>;
- }
-
- <jd>/** OPTIONS request handler */</jd>
- <ja>@RestOp</ja>(method=<jsf>OPTIONS</jsf>, path=<js>"/*"</js>)
- <jk>public</jk> Swagger doOptions(RestRequest <jv>req</jv>) {
- <jk>return new</jk> Swagger(<jk>this</jk>,
<jv>req</jv>);
- }
- }
- </p>
- <p>
- When you point your browser to this resource,
the default content type is HTML (since that's what the
- browser asks for by default).
- </p>
-
- <h5 class='figure'>HTML</h5>
- <img class='bordered' src="doc-files/Example_Html.png">
- <p>
- The REST API allows you to specify the
<code>Accept</code> header as a GET parameter, and the
- <code>plainText=true</code> parameter forces
the returned <code>Content-Type</code> to be
- <code>text/plain</code>.
- We'll use this to view the JSON-Schema document
in other languages.
- </p>
-
- <h5 class='figure'>Normal JSON</h5>
- <img class='bordered' src="doc-files/Example_Json.png">
-
- <h5 class='figure'>XML</h5>
- <img class='bordered' src="doc-files/Example_Xml.png">
-
- <h5 class='figure'>URL-Encoded</h5>
- <img class='bordered'
src="doc-files/Example_UrlEncoded.png">
-
- <h5 class='figure'>Abbreviated RDF/XML</h5>
- <img class='bordered'
src="doc-files/Example_XmlRdfAbbrev.png">
-
- <h5 class='figure'>Turtle</h5>
- <img class='bordered'
src="doc-files/Example_Turtle.png">
-
- <p>
- The full list of options for this resource can
be accessed by the <code>options</code> link on the HTML
- page.
- </p>
-
- <h5 class='figure'>Resource Options</h5>
- <img class='bordered'
src="doc-files/Example_Options.png">
- </div>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="Parse"></a>
- <h3 class='topic'>1.3 - Parsing JSON-Schema documents</h3>
- <div class='topic'>
- <p>
- Use the {@link org.apache.juneau.json.JsonParser} to
parse JSON-Schema documents into DTOs:
- </p>
- <p class='bjava'>
- <jc>// Use parser to load JSON-Schema document into JSON-Schema
DTOs</jc>
- Schema <jv>schema</jv> =
JsonParser.<jsf>DEFAULT</jsf>.parse(<jv>json</jv>, JsonSchema.<jk>class</jk>);
- </p>
- <p>
- Schema objects can also be constructed from the other
media types using the appropriate parsers.
- </p>
- </div>
-
-</div>
-<p align="center"><i><b>*** fín ***</b></i></p>
-</body>
-</html>
\ No newline at end of file
diff --git a/juneau-docs/docs/topics/04.04.00.JuneauBeanJsonSchema.md
b/juneau-docs/docs/topics/04.04.00.JuneauBeanJsonSchema.md
index 3cc89cca64..9191740173 100644
--- a/juneau-docs/docs/topics/04.04.00.JuneauBeanJsonSchema.md
+++ b/juneau-docs/docs/topics/04.04.00.JuneauBeanJsonSchema.md
@@ -5,36 +5,449 @@ slug: JuneauBeanJsonSchema
# juneau-bean-jsonschema
-The `juneau-bean-jsonschema` module provides Java beans for working with JSON
Schema documents.
+The `juneau-bean-jsonschema` module provides Java beans for working with JSON
Schema documents following the **JSON Schema Draft 2020-12** specification.
## Overview
-This module contains predefined POJOs for:
+This module contains predefined POJOs for representing and manipulating JSON
Schema documents programmatically. These beans can be serialized to any format
supported by Juneau (JSON, XML, HTML, etc.), making it easy to generate and
consume JSON Schema documents in your applications.
-- JSON Schema document structure
-- Schema validation
-- Schema generation
-- Schema manipulation
+### Key Features
-## Usage
+- **Full Draft 2020-12 Support:** All properties and validation keywords from
the latest specification
+- **Backward Compatibility:** Deprecated Draft 04 properties are still
supported for legacy schemas
+- **Fluent API:** Method chaining for intuitive schema construction
+- **Type Safety:** Uses enums and typed collections
+- **Format Agnostic:** Serialize to JSON, XML, HTML, or any other
Juneau-supported format
+
+## Basic Usage
+
+### Creating a Simple Schema
```java
import org.apache.juneau.bean.jsonschema.*;
+import org.apache.juneau.json.*;
+
+// Create a schema for a person object
+JsonSchema schema = new JsonSchema()
+ .setIdUri("https://example.com/person.schema.json")
+ .setSchemaVersionUri("https://json-schema.org/draft/2020-12/schema")
+ .setTitle("Person")
+ .setDescription("A person object")
+ .setType(JsonType.OBJECT)
+ .addProperties(
+ new JsonSchemaProperty("firstName", JsonType.STRING)
+ .setMinLength(1)
+ .setMaxLength(50),
+ new JsonSchemaProperty("lastName", JsonType.STRING)
+ .setMinLength(1)
+ .setMaxLength(50),
+ new JsonSchemaProperty("age", JsonType.INTEGER)
+ .setMinimum(0)
+ .setExclusiveMaximum(150)
+ )
+ .addRequired("firstName", "lastName");
+
+// Serialize to JSON
+String json = JsonSerializer.DEFAULT_SORTED.serialize(schema);
+```
+
+**Output:**
+```json
+{
+ "$id": "https://example.com/person.schema.json",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "description": "A person object",
+ "properties": {
+ "age": {
+ "exclusiveMaximum": 150,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "firstName": {
+ "maxLength": 50,
+ "minLength": 1,
+ "type": "string"
+ },
+ "lastName": {
+ "maxLength": 50,
+ "minLength": 1,
+ "type": "string"
+ }
+ },
+ "required": ["firstName", "lastName"],
+ "title": "Person",
+ "type": "object"
+}
+```
+
+## Common Schema Patterns
+
+### String Constraints
+
+```java
+// String with pattern and length constraints
+JsonSchema schema = new JsonSchema()
+ .setType(JsonType.STRING)
+ .setMinLength(5)
+ .setMaxLength(100)
+ .setPattern("^[A-Za-z0-9]+$")
+ .addExamples("example1", "example2");
+```
+
+### Numeric Ranges
+
+```java
+// Number with exclusive bounds (Draft 06+ syntax)
+JsonSchema schema = new JsonSchema()
+ .setType(JsonType.NUMBER)
+ .setExclusiveMinimum(0) // > 0 (not >=)
+ .setExclusiveMaximum(100) // < 100 (not <=)
+ .setMultipleOf(0.5);
+```
+
+:::note Draft 04 vs Draft 2020-12
+In Draft 04, `exclusiveMaximum` and `exclusiveMinimum` were boolean flags used
with `maximum` and `minimum`.
+In Draft 06+, they are numeric values representing the exclusive bounds
directly.
+
+**Old (Draft 04):**
+```java
+.setMaximum(100)
+.setExclusiveMaximum(true) // Boolean
+```
+
+**New (Draft 2020-12):**
+```java
+.setExclusiveMaximum(100) // Direct numeric value
+```
+:::
+
+### Enumerations
+
+```java
+// Restrict to specific values
+JsonSchema schema = new JsonSchema()
+ .setType(JsonType.STRING)
+ .addEnum("pending", "active", "completed", "cancelled");
-// Create a JSON Schema
-JsonSchema schema = JsonSchema.create()
- .type("object")
- .properties(Map.of(
- "name", JsonSchema.create().type("string"),
- "age", JsonSchema.create().type("integer")
- ))
- .build();
+// Or use const for a single value
+JsonSchema statusSchema = new JsonSchema()
+ .setConst("active");
+```
+
+### Arrays
+
+```java
+// Array of strings with item constraints
+JsonSchema schema = new JsonSchema()
+ .setType(JsonType.ARRAY)
+ .setItems(new JsonSchema()
+ .setType(JsonType.STRING)
+ .setMinLength(1)
+ )
+ .setMinItems(1)
+ .setMaxItems(10)
+ .setUniqueItems(true);
+
+// Tuple validation with prefixItems (Draft 2020-12)
+JsonSchema coordinateSchema = new JsonSchema()
+ .setType(JsonType.ARRAY)
+ .addPrefixItems(
+ new JsonSchema().setType(JsonType.NUMBER), // latitude
+ new JsonSchema().setType(JsonType.NUMBER) // longitude
+ )
+ .setItems(false); // No additional items allowed
+```
+
+### Object Properties
+
+```java
+// Object with property constraints
+JsonSchema schema = new JsonSchema()
+ .setType(JsonType.OBJECT)
+ .addProperties(
+ new JsonSchemaProperty("name", JsonType.STRING),
+ new JsonSchemaProperty("email", JsonType.STRING)
+ .setReadOnly(true), // Draft 07+
+ new JsonSchemaProperty("password", JsonType.STRING)
+ .setWriteOnly(true) // Draft 07+
+ )
+ .addRequired("name")
+ .setMinProperties(1)
+ .setMaxProperties(10)
+ .setAdditionalProperties(false); // No extra properties allowed
+```
+
+## Advanced Features
+
+### Conditional Schemas (Draft 07+)
+
+Use `if/then/else` for conditional validation:
-// Serialize to JSON Schema format
-String jsonSchema = Json.of(schema);
+```java
+JsonSchema schema = new JsonSchema()
+ .setType(JsonType.OBJECT)
+ .addProperties(
+ new JsonSchemaProperty("country", JsonType.STRING),
+ new JsonSchemaProperty("postalCode", JsonType.STRING)
+ )
+ .setIf(new JsonSchema()
+ .addProperties(
+ new JsonSchemaProperty("country").setConst("USA")
+ )
+ )
+ .setThen(new JsonSchema()
+ .addProperties(
+ new JsonSchemaProperty("postalCode")
+ .setPattern("^[0-9]{5}$")
+ )
+ )
+ .setElse(new JsonSchema()
+ .addProperties(
+ new JsonSchemaProperty("postalCode")
+ .setPattern("^[A-Z0-9]{3,10}$")
+ )
+ );
```
+### Reusable Definitions ($defs)
+
+Create reusable schema components:
+
+```java
+JsonSchema schema = new JsonSchema()
+ .setIdUri("https://example.com/product.schema.json")
+ .setType(JsonType.OBJECT)
+ // Define reusable schemas
+ .addDef("address", new JsonSchema()
+ .setType(JsonType.OBJECT)
+ .addProperties(
+ new JsonSchemaProperty("street", JsonType.STRING),
+ new JsonSchemaProperty("city", JsonType.STRING),
+ new JsonSchemaProperty("zipCode", JsonType.STRING)
+ )
+ .addRequired("street", "city")
+ )
+ .addDef("price", new JsonSchema()
+ .setType(JsonType.NUMBER)
+ .setExclusiveMinimum(0)
+ .addExamples(9.99, 19.99, 99.99)
+ )
+ // Reference definitions
+ .addProperties(
+ new JsonSchemaProperty("billingAddress")
+ .setRef("#/$defs/address"),
+ new JsonSchemaProperty("shippingAddress")
+ .setRef("#/$defs/address"),
+ new JsonSchemaProperty("price")
+ .setRef("#/$defs/price")
+ );
+```
+
+:::tip $defs vs definitions
+Draft 2020-12 uses `$defs` as the preferred keyword, but `definitions` is
still supported for backward compatibility.
+Use `addDef()` for new schemas, but `addDefinition()` will still work.
+:::
+
+### Schema Composition
+
+Combine schemas using logical operators:
+
+```java
+// allOf - must match ALL schemas
+JsonSchema allOfSchema = new JsonSchema()
+ .addAllOf(
+ new JsonSchema().setType(JsonType.STRING),
+ new JsonSchema().setMinLength(5)
+ );
+
+// anyOf - must match AT LEAST ONE schema
+JsonSchema anyOfSchema = new JsonSchema()
+ .addAnyOf(
+ new JsonSchema().setType(JsonType.STRING),
+ new JsonSchema().setType(JsonType.NUMBER)
+ );
+
+// oneOf - must match EXACTLY ONE schema
+JsonSchema oneOfSchema = new JsonSchema()
+ .addOneOf(
+ new JsonSchema().setMultipleOf(5),
+ new JsonSchema().setMultipleOf(3)
+ );
+
+// not - must NOT match schema
+JsonSchema notSchema = new JsonSchema()
+ .setNot(new JsonSchema().setType(JsonType.NULL));
+```
+
+### Dependent Schemas (Draft 2019-09+)
+
+Express dependencies between properties:
+
+```java
+// If creditCard exists, billingAddress is required
+JsonSchema schema = new JsonSchema()
+ .setType(JsonType.OBJECT)
+ .addProperties(
+ new JsonSchemaProperty("creditCard", JsonType.STRING),
+ new JsonSchemaProperty("billingAddress", JsonType.STRING)
+ )
+ .addDependentSchema("creditCard", new JsonSchema()
+ .addRequired("billingAddress")
+ );
+
+// Property-level dependencies
+schema.addDependentRequired("creditCard",
+ Arrays.asList("billingAddress", "cardholderName"));
+```
+
+## Parsing JSON Schema
+
+Parse existing JSON Schema documents:
+
+```java
+import org.apache.juneau.json.*;
+
+String jsonSchemaString = """
+ {
+ "$id": "https://example.com/schema",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "age": { "type": "integer", "minimum": 0 }
+ },
+ "required": ["name"]
+ }
+ """;
+
+JsonSchema schema = JsonParser.DEFAULT.parse(jsonSchemaString,
JsonSchema.class);
+
+// Access properties
+String title = schema.getTitle();
+Map<String, JsonSchema> props = schema.getProperties();
+JsonSchema nameProperty = schema.getProperty("name");
+```
+
+## Serialization to Other Formats
+
+Since these are standard Juneau beans, you can serialize to any supported
format:
+
+```java
+import org.apache.juneau.xml.*;
+import org.apache.juneau.html.*;
+
+JsonSchema schema = new JsonSchema()
+ .setTitle("Example")
+ .setType(JsonType.STRING);
+
+// Serialize to XML
+String xml = XmlSerializer.DEFAULT.serialize(schema);
+
+// Serialize to HTML
+String html = HtmlSerializer.DEFAULT.serialize(schema);
+```
+
+## Migration Guide
+
+### From Draft 04 to Draft 2020-12
+
+If you have existing code using Draft 04 syntax:
+
+**Property Changes:**
+- `id` → `$id` (use `setIdUri()` instead of `setId()`)
+- `definitions` → `$defs` (use `addDef()` instead of `addDefinition()`)
+
+**Semantic Changes:**
+```java
+// OLD: Draft 04 - boolean flags
+schema.setMaximum(100).setExclusiveMaximum(true);
+schema.setMinimum(0).setExclusiveMinimum(true);
+
+// NEW: Draft 2020-12 - direct numeric values
+schema.setExclusiveMaximum(100);
+schema.setExclusiveMinimum(0);
+```
+
+**Backward Compatibility:**
+The deprecated methods still work, so existing code will continue to function:
+```java
+// These still work (deprecated but supported)
+schema.setId("http://example.com/schema");
+schema.addDefinition("myDef", new JsonSchema());
+```
+
+## API Reference
+
+### Main Classes
+
+- <a href="/site/apidocs/org/apache/juneau/bean/jsonschema/JsonSchema.html"
target="_blank">`JsonSchema`</a> - Main schema bean
+- <a
href="/site/apidocs/org/apache/juneau/bean/jsonschema/JsonSchemaProperty.html"
target="_blank">`JsonSchemaProperty`</a> - Property schema (extends JsonSchema)
+- <a href="/site/apidocs/org/apache/juneau/bean/jsonschema/JsonType.html"
target="_blank">`JsonType`</a> - Enum for JSON types
+- <a href="/site/apidocs/org/apache/juneau/bean/jsonschema/JsonSchemaRef.html"
target="_blank">`JsonSchemaRef`</a> - Schema reference ($ref)
+- <a
href="/site/apidocs/org/apache/juneau/bean/jsonschema/JsonSchemaArray.html"
target="_blank">`JsonSchemaArray`</a> - Array of schemas
+- <a href="/site/apidocs/org/apache/juneau/bean/jsonschema/JsonSchemaMap.html"
target="_blank">`JsonSchemaMap`</a> - Map of schemas
+
+### Key Methods
+
+**Identity:**
+- `setIdUri(Object)` - Set schema identifier ($id)
+- `setSchemaVersionUri(Object)` - Set schema version ($schema)
+
+**Metadata:**
+- `setTitle(String)` - Human-readable title
+- `setDescription(String)` - Detailed description
+- `addExamples(Object...)` - Add example values
+
+**Type Constraints:**
+- `setType(JsonType)` - Set expected type
+- `setEnum(List)` / `addEnum(Object...)` - Restrict to specific values
+- `setConst(Object)` - Require specific value
+
+**String Constraints:**
+- `setMinLength(Integer)` / `setMaxLength(Integer)` - Length bounds
+- `setPattern(String)` - Regular expression pattern
+- `setContentMediaType(String)` / `setContentEncoding(String)` - Content
metadata
+
+**Numeric Constraints:**
+- `setMinimum(Number)` / `setMaximum(Number)` - Inclusive bounds
+- `setExclusiveMinimum(Number)` / `setExclusiveMaximum(Number)` - Exclusive
bounds
+- `setMultipleOf(Number)` - Must be multiple of value
+
+**Array Constraints:**
+- `setItems(Object)` - Schema for array items
+- `setPrefixItems(JsonSchemaArray)` - Tuple validation
+- `setMinItems(Integer)` / `setMaxItems(Integer)` - Size bounds
+- `setUniqueItems(Boolean)` - Require unique elements
+
+**Object Constraints:**
+- `addProperties(JsonSchemaProperty...)` - Define properties
+- `addRequired(String...)` - Required property names
+- `setMinProperties(Integer)` / `setMaxProperties(Integer)` - Property count
bounds
+- `setAdditionalProperties(Object)` - Allow/disallow extra properties
+- `setPatternProperties(Map)` - Pattern-based property matching
+
+**Composition:**
+- `addAllOf(JsonSchema...)` - Must match all schemas
+- `addAnyOf(JsonSchema...)` - Must match at least one
+- `addOneOf(JsonSchema...)` - Must match exactly one
+- `setNot(JsonSchema)` - Must not match schema
+
+**Conditional:**
+- `setIf(JsonSchema)` / `setThen(JsonSchema)` / `setElse(JsonSchema)` -
Conditional validation
+
+**Reusability:**
+- `addDef(String, JsonSchema)` - Add reusable definition ($defs)
+- `setRef(Object)` - Reference another schema ($ref)
+
## Dependencies
-- No external dependencies
-- Part of the `juneau-bean` module group
+- **Runtime:** `juneau-marshall` (included in `juneau-bean`)
+- **External:** None
+- **Part of:** `juneau-bean` module group
+
+## Resources
+
+- [JSON Schema 2020-12
Specification](https://json-schema.org/draft/2020-12/json-schema-core.html)
+- [JSON Schema
Validation](https://json-schema.org/draft/2020-12/json-schema-validation.html)
+- [Understanding JSON
Schema](https://json-schema.org/understanding-json-schema/)
+- [JSON Schema Store](https://www.schemastore.org/json/) - Collection of
common schemas
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/bean/jsonschema/JsonSchema_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/bean/jsonschema/JsonSchema_Test.java
index 1d59a1138a..f5ab2d1f22 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/bean/jsonschema/JsonSchema_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/bean/jsonschema/JsonSchema_Test.java
@@ -24,32 +24,37 @@ import org.apache.juneau.*;
import org.apache.juneau.json.*;
import org.junit.jupiter.api.*;
+@SuppressWarnings("deprecation")
public class JsonSchema_Test extends TestBase {
@Test void a01_schema1() throws Exception {
- var s = JsonSerializer.create().json5().ws().build();
+ var s =
JsonSerializer.create().json5().ws().sortProperties().build();
var p = JsonParser.DEFAULT;
var expected = """
{
- id: 'http://id',
'$schema': 'http://schemaVersionUri',
- title: 'title',
- description: 'description',
- type: 'number',
- definitions: {
- definition: {
- '$ref': 'http://definition'
- }
- },
- properties: {
- property: {
+ additionalItems: [
+ {
type: 'number'
}
+ ],
+ additionalProperties: {
+ '$ref': 'http://additionalProperty'
},
- patternProperties: {
- '/pattern/': {
- type: 'number'
+ allOf: [
+ {
+ '$ref': 'http://allOf'
+ }
+ ],
+ anyOf: [
+ {
+ '$ref': 'http://anyOf'
+ }
+ ],
+ definitions: {
+ definition: {
+ '$ref': 'http://definition'
}
},
dependencies: {
@@ -57,56 +62,52 @@ public class JsonSchema_Test extends TestBase {
'$ref': 'http://dependency'
}
},
- items: [
- {
- type: 'number'
- }
+ description: 'description',
+ 'enum': [
+ 'enum'
],
- multipleOf: 1,
- maximum: 2,
- exclusiveMaximum: true,
- minimum: 3,
- exclusiveMinimum: true,
- maxLength: 4,
- minLength: 5,
- pattern: '/pattern/',
- additionalItems: [
+ exclusiveMaximum: 10,
+ exclusiveMinimum: 1,
+ id: 'http://id',
+ items: [
{
type: 'number'
}
],
maxItems: 6,
- minItems: 7,
- uniqueItems: true,
+ maxLength: 4,
maxProperties: 8,
+ maximum: 2,
+ minItems: 7,
+ minLength: 5,
minProperties: 9,
- required: [
- 'required'
- ],
- additionalProperties: {
- '$ref': 'http://additionalProperty'
+ minimum: 3,
+ multipleOf: 1,
+ not: {
+ '$ref': 'http://not'
},
- 'enum': [
- 'enum'
- ],
- allOf: [
+ oneOf: [
{
- '$ref': 'http://allOf'
+ '$ref': 'http://oneOf'
}
],
- anyOf: [
- {
- '$ref': 'http://anyOf'
+ pattern: '/pattern/',
+ patternProperties: {
+ '/pattern/': {
+ type: 'number'
}
- ],
- oneOf: [
- {
- '$ref': 'http://oneOf'
+ },
+ properties: {
+ property: {
+ type: 'number'
}
+ },
+ required: [
+ 'required'
],
- not: {
- '$ref': 'http://not'
- }
+ title: 'title',
+ type: 'number',
+ uniqueItems: true
}""";
var t = getTest1();
@@ -118,29 +119,29 @@ public class JsonSchema_Test extends TestBase {
}
@Test void a02_schema2() throws Exception {
- var s = JsonSerializer.create().json5().ws().build();
+ var s =
JsonSerializer.create().json5().ws().sortProperties().build();
var p = JsonParser.DEFAULT;
var expected = """
{
- id: 'http://id',
'$schema': 'http://schemaVersionUri',
- type: [
- 'string',
- 'number'
- ],
+ additionalItems: true,
+ additionalProperties: true,
definitions: {
definition: {
id: 'http://definition'
}
},
+ id: 'http://id',
items: [
{
'$ref': 'http://items'
}
],
- additionalItems: true,
- additionalProperties: true
+ type: [
+ 'string',
+ 'number'
+ ]
}""";
var t = getTest2();
@@ -152,29 +153,33 @@ public class JsonSchema_Test extends TestBase {
}
@Test void a03_toString() throws Exception {
- var s = JsonSerializer.create().json5().ws().build();
+ var s =
JsonSerializer.create().json5().ws().sortProperties().build();
var p = JsonParser.DEFAULT;
var expected = """
{
- id: 'http://id',
'$schema': 'http://schemaVersionUri',
- title: 'title',
- description: 'description',
- type: 'number',
- definitions: {
- definition: {
- '$ref': 'http://definition'
- }
- },
- properties: {
- property: {
+ additionalItems: [
+ {
type: 'number'
}
+ ],
+ additionalProperties: {
+ '$ref': 'http://additionalProperty'
},
- patternProperties: {
- '/pattern/': {
- type: 'number'
+ allOf: [
+ {
+ '$ref': 'http://allOf'
+ }
+ ],
+ anyOf: [
+ {
+ '$ref': 'http://anyOf'
+ }
+ ],
+ definitions: {
+ definition: {
+ '$ref': 'http://definition'
}
},
dependencies: {
@@ -182,56 +187,52 @@ public class JsonSchema_Test extends TestBase {
'$ref': 'http://dependency'
}
},
- items: [
- {
- type: 'number'
- }
+ description: 'description',
+ 'enum': [
+ 'enum'
],
- multipleOf: 1,
- maximum: 2,
- exclusiveMaximum: true,
- minimum: 3,
- exclusiveMinimum: true,
- maxLength: 4,
- minLength: 5,
- pattern: '/pattern/',
- additionalItems: [
+ exclusiveMaximum: 10,
+ exclusiveMinimum: 1,
+ id: 'http://id',
+ items: [
{
type: 'number'
}
],
maxItems: 6,
- minItems: 7,
- uniqueItems: true,
+ maxLength: 4,
maxProperties: 8,
+ maximum: 2,
+ minItems: 7,
+ minLength: 5,
minProperties: 9,
- required: [
- 'required'
- ],
- additionalProperties: {
- '$ref': 'http://additionalProperty'
+ minimum: 3,
+ multipleOf: 1,
+ not: {
+ '$ref': 'http://not'
},
- 'enum': [
- 'enum'
- ],
- allOf: [
+ oneOf: [
{
- '$ref': 'http://allOf'
+ '$ref': 'http://oneOf'
}
],
- anyOf: [
- {
- '$ref': 'http://anyOf'
+ pattern: '/pattern/',
+ patternProperties: {
+ '/pattern/': {
+ type: 'number'
}
- ],
- oneOf: [
- {
- '$ref': 'http://oneOf'
+ },
+ properties: {
+ property: {
+ type: 'number'
}
+ },
+ required: [
+ 'required'
],
- not: {
- '$ref': 'http://not'
- }
+ title: 'title',
+ type: 'number',
+ uniqueItems: true
}""";
var t = getTest1();
@@ -257,9 +258,9 @@ public class JsonSchema_Test extends TestBase {
.addItems(new JsonSchema().setType(JsonType.NUMBER))
.setMultipleOf(1)
.setMaximum(2)
- .setExclusiveMaximum(true)
+ .setExclusiveMaximum(Integer.valueOf(10)) // Changed
from Boolean to Number (Draft 06+)
.setMinimum(3)
- .setExclusiveMinimum(true)
+ .setExclusiveMinimum(Integer.valueOf(1)) // Changed
from Boolean to Number (Draft 06+)
.setMaxLength(4)
.setMinLength(5)
.setPattern("/pattern/")