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/")


Reply via email to