Repository: GREsau/schemars
Pull request #294 (2024-05-19 19:38:01)

Support JSON Schema draft 2020-12 and use it by default


Patch:
diff --git a/schemars/src/gen.rs b/schemars/src/gen.rs
index 1c6fd88..6446a2c 100644
--- a/schemars/src/gen.rs
+++ b/schemars/src/gen.rs
@@ -18,18 +18,18 @@ use std::{any::Any, collections::HashSet, fmt::Debug};
 
 /// Settings to customize how Schemas are generated.
 ///
-/// The default settings currently conform to [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7), but this is liable to change in a future version of Schemars if support for other JSON Schema versions is added.
-/// If you require your generated schemas to conform to draft 7, consider using the [`draft07`](#method.draft07) method.
+/// The default settings currently conform to [JSON Schema 2020-12](https://json-schema.org/specification-links#2020-12), but this is liable to change in a future version of Schemars if support for other JSON Schema versions is added.
+/// If you rely on generated schemas conforming to draft 2020-12, consider using the [`SchemaSettings::draft2020_12()`] method.
 #[derive(Debug, Clone)]
 #[non_exhaustive]
 pub struct SchemaSettings {
-    /// If `true`, schemas for [`Option<T>`](Option) will include a `nullable` property.
+    /// If `true`, schemas for [`Option<T>`] will include a `nullable` property.
     ///
     /// This is not part of the JSON Schema spec, but is used in Swagger/OpenAPI schemas.
     ///
     /// Defaults to `false`.
     pub option_nullable: bool,
-    /// If `true`, schemas for [`Option<T>`](Option) will have `null` added to their [`type`](../schema/struct.SchemaObject.html#structfield.instance_type).
+    /// If `true`, schemas for [`Option<T>`] will have `null` added to their `type` property.
     ///
     /// Defaults to `true`.
     pub option_add_null_type: bool,
@@ -39,9 +39,9 @@ pub struct SchemaSettings {
     pub definitions_path: String,
     /// The URI of the meta-schema describing the structure of the generated schemas.
     ///
-    /// Defaults to `"http://json-schema.org/draft-07/schema#"`.
+    /// Defaults to `"https://json-schema.org/draft/2020-12/schema"`.
     pub meta_schema: Option<String>,
-    /// A list of visitors that get applied to all generated root schemas.
+    /// A list of visitors that get applied to all generated schemas.
     pub visitors: Vec<Box<dyn GenVisitor>>,
     /// Inline all subschemas instead of using references.
     ///
@@ -53,30 +53,42 @@ pub struct SchemaSettings {
 
 impl Default for SchemaSettings {
     fn default() -> SchemaSettings {
-        SchemaSettings::draft07()
+        SchemaSettings::draft2020_12()
     }
 }
 
 impl SchemaSettings {
-    /// Creates `SchemaSettings` that conform to [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7).
+    /// Creates `SchemaSettings` that conform to [JSON Schema Draft 7](https://json-schema.org/specification-links#draft-7).
     pub fn draft07() -> SchemaSettings {
         SchemaSettings {
             option_nullable: false,
             option_add_null_type: true,
             definitions_path: "#/definitions/".to_owned(),
             meta_schema: Some("http://json-schema.org/draft-07/schema#".to_owned()),
-            visitors: vec![Box::new(RemoveRefSiblings)],
+            visitors: vec![Box::new(RemoveRefSiblings), Box::new(ReplacePrefixItems)],
             inline_subschemas: false,
         }
     }
 
-    /// Creates `SchemaSettings` that conform to [JSON Schema 2019-09](https://json-schema.org/specification-links.html#2019-09-formerly-known-as-draft-8).
+    /// Creates `SchemaSettings` that conform to [JSON Schema 2019-09](https://json-schema.org/specification-links#draft-2019-09-(formerly-known-as-draft-8)).
     pub fn draft2019_09() -> SchemaSettings {
         SchemaSettings {
             option_nullable: false,
             option_add_null_type: true,
             definitions_path: "#/$defs/".to_owned(),
             meta_schema: Some("https://json-schema.org/draft/2019-09/schema".to_owned()),
+            visitors: vec![Box::new(ReplacePrefixItems)],
+            inline_subschemas: false,
+        }
+    }
+
+    /// Creates `SchemaSettings` that conform to [JSON Schema 2020-12](https://json-schema.org/specification-links#2020-12).
+    pub fn draft2020_12() -> SchemaSettings {
+        SchemaSettings {
+            option_nullable: false,
+            option_add_null_type: true,
+            definitions_path: "#/$defs/".to_owned(),
+            meta_schema: Some("https://json-schema.org/draft/2020-12/schema".to_owned()),
             visitors: Vec::new(),
             inline_subschemas: false,
         }
@@ -99,6 +111,7 @@ impl SchemaSettings {
                 }),
                 Box::new(SetSingleExample),
                 Box::new(ReplaceConstValue),
+                Box::new(ReplacePrefixItems),
             ],
             inline_subschemas: false,
         }
diff --git a/schemars/src/json_schema_impls/tuple.rs b/schemars/src/json_schema_impls/tuple.rs
index ab9a36d..204169e 100644
--- a/schemars/src/json_schema_impls/tuple.rs
+++ b/schemars/src/json_schema_impls/tuple.rs
@@ -25,7 +25,7 @@ macro_rules! tuple_impls {
                 fn json_schema(gen: &mut SchemaGenerator) -> Schema {
                     json_schema!({
                         "type": "array",
-                        "items": [
+                        "prefixItems": [
                             $(gen.subschema_for::<$name>()),+
                         ],
                         "minItems": $len,
diff --git a/schemars/src/ser.rs b/schemars/src/ser.rs
index 8be7b34..75ae6ca 100644
--- a/schemars/src/ser.rs
+++ b/schemars/src/ser.rs
@@ -378,7 +378,7 @@ impl serde::ser::SerializeTuple for SerializeTuple<'_> {
         let len = self.items.len();
         let mut schema = json_schema!({
             "type": "array",
-            "items": self.items,
+            "prefixItems": self.items,
             "maxItems": len,
             "minItems": len,
         });
diff --git a/schemars/src/visit.rs b/schemars/src/visit.rs
index a9ca787..30bdf0d 100644
--- a/schemars/src/visit.rs
+++ b/schemars/src/visit.rs
@@ -50,15 +50,15 @@ pub fn visit_schema<V: Visitor + ?Sized>(v: &mut V, schema: &mut Schema) {
                 | "if"
                 | "then"
                 | "else"
-                | "additionalItems"
                 | "contains"
                 | "additionalProperties"
-                | "propertyNames" => {
+                | "propertyNames"
+                | "items" => {
                     if let Ok(subschema) = value.try_into() {
                         v.visit_schema(subschema)
                     }
                 }
-                "allOf" | "anyOf" | "oneOf" => {
+                "allOf" | "anyOf" | "oneOf" | "prefixItems" => {
                     if let Some(array) = value.as_array_mut() {
                         for value in array {
                             if let Ok(subschema) = value.try_into() {
@@ -67,17 +67,6 @@ pub fn visit_schema<V: Visitor + ?Sized>(v: &mut V, schema: &mut Schema) {
                         }
                     }
                 }
-                "items" => {
-                    if let Some(array) = value.as_array_mut() {
-                        for value in array {
-                            if let Ok(subschema) = value.try_into() {
-                                v.visit_schema(subschema)
-                            }
-                        }
-                    } else if let Ok(subschema) = value.try_into() {
-                        v.visit_schema(subschema)
-                    }
-                }
                 "properties" | "patternProperties" => {
                     if let Some(obj) = value.as_object_mut() {
                         for value in obj.values_mut() {
@@ -126,7 +115,7 @@ impl Visitor for ReplaceBoolSchemas {
 
 /// This visitor will restructure JSON Schema objects so that the `$ref` property will never appear alongside any other properties.
 ///
-/// This is useful for dialects of JSON Schema (e.g. Draft 7) that do not support other properties alongside `$ref`.
+/// This is useful for versions of JSON Schema (e.g. Draft 7) that do not support other properties alongside `$ref`.
 #[derive(Debug, Clone)]
 pub struct RemoveRefSiblings;
 
@@ -187,3 +176,27 @@ impl Visitor for ReplaceConstValue {
         }
     }
 }
+
+/// This visitor will rename the `prefixItems` schema property to `items`.
+///
+/// If the schema contains both `prefixItems` and `items`, then this additionally renames `items` to `additionalItems`.
+///
+/// This is useful for versions of JSON Schema (e.g. Draft 7) that do not support the `prefixItems` property.
+#[derive(Debug, Clone)]
+pub struct ReplacePrefixItems;
+
+impl Visitor for ReplacePrefixItems {
+    fn visit_schema(&mut self, schema: &mut Schema) {
+        visit_schema(self, schema);
+
+        if let Some(obj) = schema.as_object_mut() {
+            if let Some(prefix_items) = obj.remove("prefixItems") {
+                let previous_items = obj.insert("items".to_owned(), prefix_items);
+
+                if let Some(previous_items) = previous_items {
+                    obj.insert("additionalItems".to_owned(), previous_items);
+                }
+            }
+        }
+    }
+}
diff --git a/schemars_derive/src/schema_exprs.rs b/schemars_derive/src/schema_exprs.rs
index 6357172..87e789e 100644
--- a/schemars_derive/src/schema_exprs.rs
+++ b/schemars_derive/src/schema_exprs.rs
@@ -422,7 +422,7 @@ fn expr_for_tuple_struct(fields: &[Field]) -> TokenStream {
     quote! {
         schemars::json_schema!({
             "type": "array",
-            "items": [#((#fields)),*],
+            "prefixItems": [#((#fields)),*],
             "minItems": #len,
             "maxItems": #len,
         })


Test patch:
diff --git a/schemars/tests/expected/arrayvec.json b/schemars/tests/expected/arrayvec.json
index 3de09a0..998d087 100644
--- a/schemars/tests/expected/arrayvec.json
+++ b/schemars/tests/expected/arrayvec.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Array_up_to_size_16_of_int32",
   "type": "array",
   "items": {
diff --git a/schemars/tests/expected/arrayvec_string.json b/schemars/tests/expected/arrayvec_string.json
index ad174d8..0604332 100644
--- a/schemars/tests/expected/arrayvec_string.json
+++ b/schemars/tests/expected/arrayvec_string.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "string",
   "type": "string"
 }
\ No newline at end of file
diff --git a/schemars/tests/expected/bigdecimal04.json b/schemars/tests/expected/bigdecimal04.json
index 855db6f..e94ca27 100644
--- a/schemars/tests/expected/bigdecimal04.json
+++ b/schemars/tests/expected/bigdecimal04.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Decimal",
   "type": "string",
   "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
diff --git a/schemars/tests/expected/bound.json b/schemars/tests/expected/bound.json
index e4ceb13..a5645c6 100644
--- a/schemars/tests/expected/bound.json
+++ b/schemars/tests/expected/bound.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyContainer",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/bytes.json b/schemars/tests/expected/bytes.json
index 8618a7f..80486c1 100644
--- a/schemars/tests/expected/bytes.json
+++ b/schemars/tests/expected/bytes.json
@@ -1,8 +1,8 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Tuple_of_Array_of_uint8_and_Array_of_uint8",
   "type": "array",
-  "items": [
+  "prefixItems": [
     {
       "type": "array",
       "items": {
diff --git a/schemars/tests/expected/chrono-types.json b/schemars/tests/expected/chrono-types.json
index ce03621..de26130 100644
--- a/schemars/tests/expected/chrono-types.json
+++ b/schemars/tests/expected/chrono-types.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "ChronoTypes",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/crate_alias.json b/schemars/tests/expected/crate_alias.json
index e88a449..c2f1430 100644
--- a/schemars/tests/expected/crate_alias.json
+++ b/schemars/tests/expected/crate_alias.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Struct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/default.json b/schemars/tests/expected/default.json
index 88ad12a..65b6a66 100644
--- a/schemars/tests/expected/default.json
+++ b/schemars/tests/expected/default.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyStruct",
   "type": "object",
   "properties": {
@@ -13,21 +13,17 @@
       "default": false
     },
     "my_struct2": {
-      "default": "i:0 b:false",
-      "allOf": [
-        {
-          "$ref": "#/definitions/MyStruct2"
-        }
-      ]
+      "$ref": "#/$defs/MyStruct2",
+      "default": "i:0 b:false"
     },
     "my_struct2_default_skipped": {
-      "$ref": "#/definitions/MyStruct2"
+      "$ref": "#/$defs/MyStruct2"
     },
     "not_serialize": {
-      "$ref": "#/definitions/NotSerialize"
+      "$ref": "#/$defs/NotSerialize"
     }
   },
-  "definitions": {
+  "$defs": {
     "MyStruct2": {
       "type": "object",
       "properties": {
diff --git a/schemars/tests/expected/deprecated-enum.json b/schemars/tests/expected/deprecated-enum.json
index e871160..a61c322 100644
--- a/schemars/tests/expected/deprecated-enum.json
+++ b/schemars/tests/expected/deprecated-enum.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "DeprecatedEnum",
   "oneOf": [
     {
diff --git a/schemars/tests/expected/deprecated-struct.json b/schemars/tests/expected/deprecated-struct.json
index 2b25c34..b7396ab 100644
--- a/schemars/tests/expected/deprecated-struct.json
+++ b/schemars/tests/expected/deprecated-struct.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "DeprecatedStruct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/doc_comments_enum.json b/schemars/tests/expected/doc_comments_enum.json
index 7d9321f..b2e8f94 100644
--- a/schemars/tests/expected/doc_comments_enum.json
+++ b/schemars/tests/expected/doc_comments_enum.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "This is the enum's title",
   "description": "This is the enum's description.",
   "oneOf": [
diff --git a/schemars/tests/expected/doc_comments_override.json b/schemars/tests/expected/doc_comments_override.json
index 0f90433..b184d2a 100644
--- a/schemars/tests/expected/doc_comments_override.json
+++ b/schemars/tests/expected/doc_comments_override.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "OverrideDocs struct",
   "description": "New description",
   "type": "object",
diff --git a/schemars/tests/expected/doc_comments_struct.json b/schemars/tests/expected/doc_comments_struct.json
index 103a71a..655121a 100644
--- a/schemars/tests/expected/doc_comments_struct.json
+++ b/schemars/tests/expected/doc_comments_struct.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "This is the struct's title",
   "description": "This is the struct's description.",
   "type": "object",
@@ -14,11 +14,7 @@
     },
     "my_unit": {
       "description": "A unit struct instance",
-      "allOf": [
-        {
-          "$ref": "#/definitions/MyUnitStruct"
-        }
-      ]
+      "$ref": "#/$defs/MyUnitStruct"
     }
   },
   "required": [
@@ -26,7 +22,7 @@
     "my_undocumented_bool",
     "my_unit"
   ],
-  "definitions": {
+  "$defs": {
     "MyUnitStruct": {
       "title": "A Unit",
       "type": "null"
diff --git a/schemars/tests/expected/duration_and_systemtime.json b/schemars/tests/expected/duration_and_systemtime.json
index bb25dcd..7e301e5 100644
--- a/schemars/tests/expected/duration_and_systemtime.json
+++ b/schemars/tests/expected/duration_and_systemtime.json
@@ -1,20 +1,20 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyStruct",
   "type": "object",
   "properties": {
     "duration": {
-      "$ref": "#/definitions/Duration"
+      "$ref": "#/$defs/Duration"
     },
     "time": {
-      "$ref": "#/definitions/SystemTime"
+      "$ref": "#/$defs/SystemTime"
     }
   },
   "required": [
     "duration",
     "time"
   ],
-  "definitions": {
+  "$defs": {
     "Duration": {
       "type": "object",
       "properties": {
diff --git a/schemars/tests/expected/either.json b/schemars/tests/expected/either.json
index 807c9c9..18d8f51 100644
--- a/schemars/tests/expected/either.json
+++ b/schemars/tests/expected/either.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Either_int32_or_Either_boolean_or_null",
   "anyOf": [
     {
diff --git a/schemars/tests/expected/enum-adjacent-tagged-duf.json b/schemars/tests/expected/enum-adjacent-tagged-duf.json
index b9cb5fa..dfb3bb8 100644
--- a/schemars/tests/expected/enum-adjacent-tagged-duf.json
+++ b/schemars/tests/expected/enum-adjacent-tagged-duf.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Adjacent",
   "oneOf": [
     {
@@ -49,7 +49,7 @@
           ]
         },
         "c": {
-          "$ref": "#/definitions/UnitStruct"
+          "$ref": "#/$defs/UnitStruct"
         }
       },
       "required": [
@@ -68,7 +68,7 @@
           ]
         },
         "c": {
-          "$ref": "#/definitions/Struct"
+          "$ref": "#/$defs/Struct"
         }
       },
       "required": [
@@ -121,7 +121,7 @@
         },
         "c": {
           "type": "array",
-          "items": [
+          "prefixItems": [
             {
               "type": "integer",
               "format": "int32"
@@ -176,7 +176,7 @@
       "additionalProperties": false
     }
   ],
-  "definitions": {
+  "$defs": {
     "UnitStruct": {
       "type": "null"
     },
diff --git a/schemars/tests/expected/enum-adjacent-tagged.json b/schemars/tests/expected/enum-adjacent-tagged.json
index de77713..c631ae5 100644
--- a/schemars/tests/expected/enum-adjacent-tagged.json
+++ b/schemars/tests/expected/enum-adjacent-tagged.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Adjacent",
   "oneOf": [
     {
@@ -47,7 +47,7 @@
           ]
         },
         "c": {
-          "$ref": "#/definitions/UnitStruct"
+          "$ref": "#/$defs/UnitStruct"
         }
       },
       "required": [
@@ -65,7 +65,7 @@
           ]
         },
         "c": {
-          "$ref": "#/definitions/Struct"
+          "$ref": "#/$defs/Struct"
         }
       },
       "required": [
@@ -115,7 +115,7 @@
         },
         "c": {
           "type": "array",
-          "items": [
+          "prefixItems": [
             {
               "type": "integer",
               "format": "int32"
@@ -167,7 +167,7 @@
       ]
     }
   ],
-  "definitions": {
+  "$defs": {
     "UnitStruct": {
       "type": "null"
     },
diff --git a/schemars/tests/expected/enum-external-duf.json b/schemars/tests/expected/enum-external-duf.json
index a483535..76be5b3 100644
--- a/schemars/tests/expected/enum-external-duf.json
+++ b/schemars/tests/expected/enum-external-duf.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "External",
   "oneOf": [
     {
@@ -28,7 +28,7 @@
       "type": "object",
       "properties": {
         "unitStructNewType": {
-          "$ref": "#/definitions/UnitStruct"
+          "$ref": "#/$defs/UnitStruct"
         }
       },
       "required": [
@@ -40,7 +40,7 @@
       "type": "object",
       "properties": {
         "structNewType": {
-          "$ref": "#/definitions/Struct"
+          "$ref": "#/$defs/Struct"
         }
       },
       "required": [
@@ -79,7 +79,7 @@
       "properties": {
         "tuple": {
           "type": "array",
-          "items": [
+          "prefixItems": [
             {
               "type": "integer",
               "format": "int32"
@@ -111,7 +111,7 @@
       "additionalProperties": false
     }
   ],
-  "definitions": {
+  "$defs": {
     "UnitStruct": {
       "type": "null"
     },
diff --git a/schemars/tests/expected/enum-external.json b/schemars/tests/expected/enum-external.json
index 8a1de2b..3c660fb 100644
--- a/schemars/tests/expected/enum-external.json
+++ b/schemars/tests/expected/enum-external.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "External",
   "oneOf": [
     {
@@ -28,7 +28,7 @@
       "type": "object",
       "properties": {
         "unitStructNewType": {
-          "$ref": "#/definitions/UnitStruct"
+          "$ref": "#/$defs/UnitStruct"
         }
       },
       "required": [
@@ -40,7 +40,7 @@
       "type": "object",
       "properties": {
         "structNewType": {
-          "$ref": "#/definitions/Struct"
+          "$ref": "#/$defs/Struct"
         }
       },
       "required": [
@@ -78,7 +78,7 @@
       "properties": {
         "tuple": {
           "type": "array",
-          "items": [
+          "prefixItems": [
             {
               "type": "integer",
               "format": "int32"
@@ -110,7 +110,7 @@
       "additionalProperties": false
     }
   ],
-  "definitions": {
+  "$defs": {
     "UnitStruct": {
       "type": "null"
     },
diff --git a/schemars/tests/expected/enum-internal-duf.json b/schemars/tests/expected/enum-internal-duf.json
index de51ba1..73e4743 100644
--- a/schemars/tests/expected/enum-internal-duf.json
+++ b/schemars/tests/expected/enum-internal-duf.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Internal",
   "oneOf": [
     {
diff --git a/schemars/tests/expected/enum-internal.json b/schemars/tests/expected/enum-internal.json
index a5dffe3..2fd9770 100644
--- a/schemars/tests/expected/enum-internal.json
+++ b/schemars/tests/expected/enum-internal.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Internal",
   "oneOf": [
     {
diff --git a/schemars/tests/expected/enum-repr-with-attrs.json b/schemars/tests/expected/enum-repr-with-attrs.json
index 7070de8..89d941b 100644
--- a/schemars/tests/expected/enum-repr-with-attrs.json
+++ b/schemars/tests/expected/enum-repr-with-attrs.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Renamed",
   "description": "Description from comment",
   "type": "integer",
diff --git a/schemars/tests/expected/enum-repr.json b/schemars/tests/expected/enum-repr.json
index 92d6f3a..b3e6bb9 100644
--- a/schemars/tests/expected/enum-repr.json
+++ b/schemars/tests/expected/enum-repr.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Enum",
   "type": "integer",
   "enum": [
diff --git a/schemars/tests/expected/enum-simple-internal-duf.json b/schemars/tests/expected/enum-simple-internal-duf.json
index 7fc20c1..aaf1eef 100644
--- a/schemars/tests/expected/enum-simple-internal-duf.json
+++ b/schemars/tests/expected/enum-simple-internal-duf.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "SimpleInternal",
   "oneOf": [
     {
diff --git a/schemars/tests/expected/enum-simple-internal.json b/schemars/tests/expected/enum-simple-internal.json
index 050089c..e955d2a 100644
--- a/schemars/tests/expected/enum-simple-internal.json
+++ b/schemars/tests/expected/enum-simple-internal.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "SimpleInternal",
   "oneOf": [
     {
diff --git a/schemars/tests/expected/enum-unit-doc.json b/schemars/tests/expected/enum-unit-doc.json
index 86160e8..1000435 100644
--- a/schemars/tests/expected/enum-unit-doc.json
+++ b/schemars/tests/expected/enum-unit-doc.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "SoundOfMusic",
   "oneOf": [
     {
diff --git a/schemars/tests/expected/enum-untagged-duf.json b/schemars/tests/expected/enum-untagged-duf.json
index 13a7d0a..58bdbe1 100644
--- a/schemars/tests/expected/enum-untagged-duf.json
+++ b/schemars/tests/expected/enum-untagged-duf.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Untagged",
   "anyOf": [
     {
@@ -12,10 +12,10 @@
       }
     },
     {
-      "$ref": "#/definitions/UnitStruct"
+      "$ref": "#/$defs/UnitStruct"
     },
     {
-      "$ref": "#/definitions/Struct"
+      "$ref": "#/$defs/Struct"
     },
     {
       "type": "object",
@@ -36,7 +36,7 @@
     },
     {
       "type": "array",
-      "items": [
+      "prefixItems": [
         {
           "type": "integer",
           "format": "int32"
@@ -53,7 +53,7 @@
       "format": "int32"
     }
   ],
-  "definitions": {
+  "$defs": {
     "UnitStruct": {
       "type": "null"
     },
diff --git a/schemars/tests/expected/enum-untagged.json b/schemars/tests/expected/enum-untagged.json
index ed72b43..643cd20 100644
--- a/schemars/tests/expected/enum-untagged.json
+++ b/schemars/tests/expected/enum-untagged.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Untagged",
   "anyOf": [
     {
@@ -12,10 +12,10 @@
       }
     },
     {
-      "$ref": "#/definitions/UnitStruct"
+      "$ref": "#/$defs/UnitStruct"
     },
     {
-      "$ref": "#/definitions/Struct"
+      "$ref": "#/$defs/Struct"
     },
     {
       "type": "object",
@@ -35,7 +35,7 @@
     },
     {
       "type": "array",
-      "items": [
+      "prefixItems": [
         {
           "type": "integer",
           "format": "int32"
@@ -52,7 +52,7 @@
       "format": "int32"
     }
   ],
-  "definitions": {
+  "$defs": {
     "UnitStruct": {
       "type": "null"
     },
diff --git a/schemars/tests/expected/enumset.json b/schemars/tests/expected/enumset.json
index 0f9baa2..72a39a1 100644
--- a/schemars/tests/expected/enumset.json
+++ b/schemars/tests/expected/enumset.json
@@ -1,12 +1,12 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Set_of_Foo",
   "type": "array",
   "uniqueItems": true,
   "items": {
-    "$ref": "#/definitions/Foo"
+    "$ref": "#/$defs/Foo"
   },
-  "definitions": {
+  "$defs": {
     "Foo": {
       "type": "string",
       "enum": [
diff --git a/schemars/tests/expected/examples.json b/schemars/tests/expected/examples.json
index 9f0a505..b891aa0 100644
--- a/schemars/tests/expected/examples.json
+++ b/schemars/tests/expected/examples.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Struct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/flatten.json b/schemars/tests/expected/flatten.json
index 4ea7094..7dfd54e 100644
--- a/schemars/tests/expected/flatten.json
+++ b/schemars/tests/expected/flatten.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Flat",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/from_json_value.json b/schemars/tests/expected/from_json_value.json
index 6cc1ecc..b217fad 100644
--- a/schemars/tests/expected/from_json_value.json
+++ b/schemars/tests/expected/from_json_value.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "type": "object",
   "properties": {
     "zero": {
diff --git a/schemars/tests/expected/indexmap.json b/schemars/tests/expected/indexmap.json
index 318bf9b..8ba90a8 100644
--- a/schemars/tests/expected/indexmap.json
+++ b/schemars/tests/expected/indexmap.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "IndexMapTypes",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/inline-subschemas-recursive.json b/schemars/tests/expected/inline-subschemas-recursive.json
index 0c1eebe..21f7f31 100644
--- a/schemars/tests/expected/inline-subschemas-recursive.json
+++ b/schemars/tests/expected/inline-subschemas-recursive.json
@@ -1,12 +1,12 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "RecursiveOuter",
   "type": "object",
   "properties": {
     "direct": {
       "anyOf": [
         {
-          "$ref": "#/definitions/RecursiveOuter"
+          "$ref": "#/$defs/RecursiveOuter"
         },
         {
           "type": "null"
@@ -20,7 +20,7 @@
       ],
       "properties": {
         "recursive": {
-          "$ref": "#/definitions/RecursiveOuter"
+          "$ref": "#/$defs/RecursiveOuter"
         }
       },
       "required": [
@@ -28,14 +28,14 @@
       ]
     }
   },
-  "definitions": {
+  "$defs": {
     "RecursiveOuter": {
       "type": "object",
       "properties": {
         "direct": {
           "anyOf": [
             {
-              "$ref": "#/definitions/RecursiveOuter"
+              "$ref": "#/$defs/RecursiveOuter"
             },
             {
               "type": "null"
@@ -49,7 +49,7 @@
           ],
           "properties": {
             "recursive": {
-              "$ref": "#/definitions/RecursiveOuter"
+              "$ref": "#/$defs/RecursiveOuter"
             }
           },
           "required": [
diff --git a/schemars/tests/expected/inline-subschemas.json b/schemars/tests/expected/inline-subschemas.json
index 7ba76d5..cbee457 100644
--- a/schemars/tests/expected/inline-subschemas.json
+++ b/schemars/tests/expected/inline-subschemas.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyJob",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/macro_built_enum.json b/schemars/tests/expected/macro_built_enum.json
index 4fedbb2..b27df44 100644
--- a/schemars/tests/expected/macro_built_enum.json
+++ b/schemars/tests/expected/macro_built_enum.json
@@ -1,12 +1,12 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "OuterEnum",
   "oneOf": [
     {
       "type": "object",
       "properties": {
         "InnerStruct": {
-          "$ref": "#/definitions/InnerStruct"
+          "$ref": "#/$defs/InnerStruct"
         }
       },
       "required": [
@@ -15,7 +15,7 @@
       "additionalProperties": false
     }
   ],
-  "definitions": {
+  "$defs": {
     "InnerStruct": {
       "type": "object",
       "properties": {
diff --git a/schemars/tests/expected/macro_built_struct.json b/schemars/tests/expected/macro_built_struct.json
index 74a279c..1d0fd08 100644
--- a/schemars/tests/expected/macro_built_struct.json
+++ b/schemars/tests/expected/macro_built_struct.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "A",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/no-variants.json b/schemars/tests/expected/no-variants.json
index efe2853..14de7f4 100644
--- a/schemars/tests/expected/no-variants.json
+++ b/schemars/tests/expected/no-variants.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "NoVariants",
   "type": "string",
   "enum": []
diff --git a/schemars/tests/expected/nonzero_ints.json b/schemars/tests/expected/nonzero_ints.json
index 97dee99..432e3b0 100644
--- a/schemars/tests/expected/nonzero_ints.json
+++ b/schemars/tests/expected/nonzero_ints.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyStruct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/os_strings.json b/schemars/tests/expected/os_strings.json
index b422026..72e0be1 100644
--- a/schemars/tests/expected/os_strings.json
+++ b/schemars/tests/expected/os_strings.json
@@ -1,20 +1,20 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "OsStrings",
   "type": "object",
   "properties": {
     "owned": {
-      "$ref": "#/definitions/OsString"
+      "$ref": "#/$defs/OsString"
     },
     "borrowed": {
-      "$ref": "#/definitions/OsString"
+      "$ref": "#/$defs/OsString"
     }
   },
   "required": [
     "owned",
     "borrowed"
   ],
-  "definitions": {
+  "$defs": {
     "OsString": {
       "oneOf": [
         {
diff --git a/schemars/tests/expected/property-name-struct.json b/schemars/tests/expected/property-name-struct.json
index 1aa6e78..82ea9ed 100644
--- a/schemars/tests/expected/property-name-struct.json
+++ b/schemars/tests/expected/property-name-struct.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyStruct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/range.json b/schemars/tests/expected/range.json
index 25f7389..64db4bd 100644
--- a/schemars/tests/expected/range.json
+++ b/schemars/tests/expected/range.json
@@ -1,16 +1,16 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyStruct",
   "type": "object",
   "properties": {
     "range": {
-      "$ref": "#/definitions/Range_of_uint"
+      "$ref": "#/$defs/Range_of_uint"
     },
     "inclusive": {
-      "$ref": "#/definitions/Range_of_double"
+      "$ref": "#/$defs/Range_of_double"
     },
     "bound": {
-      "$ref": "#/definitions/Bound_of_string"
+      "$ref": "#/$defs/Bound_of_string"
     }
   },
   "required": [
@@ -18,7 +18,7 @@
     "inclusive",
     "bound"
   ],
-  "definitions": {
+  "$defs": {
     "Range_of_uint": {
       "type": "object",
       "properties": {
diff --git a/schemars/tests/expected/remote_derive.json b/schemars/tests/expected/remote_derive.json
index 0f27ad3..760630d 100644
--- a/schemars/tests/expected/remote_derive.json
+++ b/schemars/tests/expected/remote_derive.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Process",
   "type": "object",
   "properties": {
@@ -7,33 +7,25 @@
       "type": "string"
     },
     "wall_time": {
-      "$ref": "#/definitions/Duration"
+      "$ref": "#/$defs/Duration"
     },
     "user_cpu_time": {
+      "$ref": "#/$defs/Duration",
       "default": {
         "secs": 0,
         "nanos": 0
-      },
-      "allOf": [
-        {
-          "$ref": "#/definitions/Duration"
-        }
-      ]
+      }
     },
     "system_cpu_time": {
-      "default": "0.000000000s",
-      "allOf": [
-        {
-          "$ref": "#/definitions/Duration"
-        }
-      ]
+      "$ref": "#/$defs/Duration",
+      "default": "0.000000000s"
     }
   },
   "required": [
     "command_line",
     "wall_time"
   ],
-  "definitions": {
+  "$defs": {
     "Duration": {
       "type": "object",
       "properties": {
diff --git a/schemars/tests/expected/remote_derive_generic.json b/schemars/tests/expected/remote_derive_generic.json
index f6ba3ef..bef4d6a 100644
--- a/schemars/tests/expected/remote_derive_generic.json
+++ b/schemars/tests/expected/remote_derive_generic.json
@@ -1,16 +1,16 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyStruct_for_int32",
   "type": "object",
   "properties": {
     "byte_or_bool2": {
-      "$ref": "#/definitions/Or_for_uint8_and_boolean"
+      "$ref": "#/$defs/Or_for_uint8_and_boolean"
     },
     "unit_or_t2": {
-      "$ref": "#/definitions/Or_for_null_and_int32"
+      "$ref": "#/$defs/Or_for_null_and_int32"
     },
     "s": {
-      "$ref": "#/definitions/Str"
+      "$ref": "#/$defs/Str"
     },
     "fake_map": {
       "type": "object",
@@ -29,7 +29,7 @@
     "s",
     "fake_map"
   ],
-  "definitions": {
+  "$defs": {
     "Or_for_uint8_and_boolean": {
       "anyOf": [
         {
diff --git a/schemars/tests/expected/result.json b/schemars/tests/expected/result.json
index 8a25a0e..b468835 100644
--- a/schemars/tests/expected/result.json
+++ b/schemars/tests/expected/result.json
@@ -1,27 +1,27 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Container",
   "type": "object",
   "properties": {
     "result1": {
-      "$ref": "#/definitions/Result_of_MyStruct_or_Array_of_string"
+      "$ref": "#/$defs/Result_of_MyStruct_or_Array_of_string"
     },
     "result2": {
-      "$ref": "#/definitions/Result_of_boolean_or_null"
+      "$ref": "#/$defs/Result_of_boolean_or_null"
     }
   },
   "required": [
     "result1",
     "result2"
   ],
-  "definitions": {
+  "$defs": {
     "Result_of_MyStruct_or_Array_of_string": {
       "oneOf": [
         {
           "type": "object",
           "properties": {
             "Ok": {
-              "$ref": "#/definitions/MyStruct"
+              "$ref": "#/$defs/MyStruct"
             }
           },
           "required": [
diff --git a/schemars/tests/expected/rust_decimal.json b/schemars/tests/expected/rust_decimal.json
index 855db6f..e94ca27 100644
--- a/schemars/tests/expected/rust_decimal.json
+++ b/schemars/tests/expected/rust_decimal.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Decimal",
   "type": "string",
   "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
diff --git a/schemars/tests/expected/same_name.json b/schemars/tests/expected/same_name.json
index ebea3fe..fb65854 100644
--- a/schemars/tests/expected/same_name.json
+++ b/schemars/tests/expected/same_name.json
@@ -1,20 +1,20 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Config2",
   "type": "object",
   "properties": {
     "a_cfg": {
-      "$ref": "#/definitions/Config"
+      "$ref": "#/$defs/Config"
     },
     "b_cfg": {
-      "$ref": "#/definitions/Config2"
+      "$ref": "#/$defs/Config2"
     }
   },
   "required": [
     "a_cfg",
     "b_cfg"
   ],
-  "definitions": {
+  "$defs": {
     "Config": {
       "type": "object",
       "properties": {
diff --git a/schemars/tests/expected/schema-name-const-generics.json b/schemars/tests/expected/schema-name-const-generics.json
index 6bb3ab1..3c2edcc 100644
--- a/schemars/tests/expected/schema-name-const-generics.json
+++ b/schemars/tests/expected/schema-name-const-generics.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "const-generics-z-42",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/schema-name-custom.json b/schemars/tests/expected/schema-name-custom.json
index 447edbd..70b4d98 100644
--- a/schemars/tests/expected/schema-name-custom.json
+++ b/schemars/tests/expected/schema-name-custom.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "a-new-name-Array_of_string-int32-int32",
   "type": "object",
   "properties": {
@@ -20,7 +20,7 @@
       }
     },
     "inner": {
-      "$ref": "#/definitions/another-new-name"
+      "$ref": "#/$defs/another-new-name"
     }
   },
   "required": [
@@ -30,7 +30,7 @@
     "w",
     "inner"
   ],
-  "definitions": {
+  "$defs": {
     "another-new-name": {
       "type": "object",
       "properties": {
diff --git a/schemars/tests/expected/schema-name-default.json b/schemars/tests/expected/schema-name-default.json
index bd2ab9a..2243ddd 100644
--- a/schemars/tests/expected/schema-name-default.json
+++ b/schemars/tests/expected/schema-name-default.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyStruct_for_int32_and_null_and_boolean_and_Array_of_string",
   "type": "object",
   "properties": {
@@ -20,7 +20,7 @@
       }
     },
     "inner": {
-      "$ref": "#/definitions/MySimpleStruct"
+      "$ref": "#/$defs/MySimpleStruct"
     }
   },
   "required": [
@@ -30,7 +30,7 @@
     "w",
     "inner"
   ],
-  "definitions": {
+  "$defs": {
     "MySimpleStruct": {
       "type": "object",
       "properties": {
diff --git a/schemars/tests/expected/schema-name-mixed-generics.json b/schemars/tests/expected/schema-name-mixed-generics.json
index 4342410..85c6792 100644
--- a/schemars/tests/expected/schema-name-mixed-generics.json
+++ b/schemars/tests/expected/schema-name-mixed-generics.json
@@ -1,10 +1,10 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MixedGenericStruct_for_MyStruct_for_int32_and_null_and_boolean_and_Array_of_string_and_42_and_z",
   "type": "object",
   "properties": {
     "generic": {
-      "$ref": "#/definitions/MyStruct_for_int32_and_null_and_boolean_and_Array_of_string"
+      "$ref": "#/$defs/MyStruct_for_int32_and_null_and_boolean_and_Array_of_string"
     },
     "foo": {
       "type": "integer",
@@ -15,7 +15,7 @@
     "generic",
     "foo"
   ],
-  "definitions": {
+  "$defs": {
     "MyStruct_for_int32_and_null_and_boolean_and_Array_of_string": {
       "type": "object",
       "properties": {
@@ -36,7 +36,7 @@
           }
         },
         "inner": {
-          "$ref": "#/definitions/MySimpleStruct"
+          "$ref": "#/$defs/MySimpleStruct"
         }
       },
       "required": [
diff --git a/schemars/tests/expected/schema_settings-2019_09.json b/schemars/tests/expected/schema_settings-2019_09.json
index 568ce85..6b6dc61 100644
--- a/schemars/tests/expected/schema_settings-2019_09.json
+++ b/schemars/tests/expected/schema_settings-2019_09.json
@@ -25,12 +25,32 @@
           "type": "null"
         }
       ]
+    },
+    "tuples": {
+      "type": "array",
+      "items": {
+        "type": "array",
+        "items": [
+          {
+            "type": "integer",
+            "format": "uint8",
+            "minimum": 0
+          },
+          {
+            "type": "integer",
+            "format": "int64"
+          }
+        ],
+        "minItems": 2,
+        "maxItems": 2
+      }
     }
   },
   "required": [
     "int",
     "values",
-    "value"
+    "value",
+    "tuples"
   ],
   "$defs": {
     "Inner": {
diff --git a/schemars/tests/expected/schema_settings-2020_12.json b/schemars/tests/expected/schema_settings-2020_12.json
new file mode 100644
index 0000000..7964058
--- /dev/null
+++ b/schemars/tests/expected/schema_settings-2020_12.json
@@ -0,0 +1,83 @@
+{
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
+  "title": "Outer",
+  "type": "object",
+  "properties": {
+    "int": {
+      "type": "integer",
+      "format": "int32",
+      "examples": [
+        8,
+        null
+      ]
+    },
+    "values": {
+      "type": "object",
+      "additionalProperties": true
+    },
+    "value": true,
+    "inner": {
+      "anyOf": [
+        {
+          "$ref": "#/$defs/Inner"
+        },
+        {
+          "type": "null"
+        }
+      ]
+    },
+    "tuples": {
+      "type": "array",
+      "items": {
+        "type": "array",
+        "prefixItems": [
+          {
+            "type": "integer",
+            "format": "uint8",
+            "minimum": 0
+          },
+          {
+            "type": "integer",
+            "format": "int64"
+          }
+        ],
+        "minItems": 2,
+        "maxItems": 2
+      }
+    }
+  },
+  "required": [
+    "int",
+    "values",
+    "value",
+    "tuples"
+  ],
+  "$defs": {
+    "Inner": {
+      "oneOf": [
+        {
+          "type": "string",
+          "enum": [
+            "UndocumentedUnit1",
+            "UndocumentedUnit2"
+          ]
+        },
+        {
+          "description": "This is a documented unit variant",
+          "type": "string",
+          "const": "DocumentedUnit"
+        },
+        {
+          "type": "object",
+          "properties": {
+            "ValueNewType": true
+          },
+          "required": [
+            "ValueNewType"
+          ],
+          "additionalProperties": false
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/schemars/tests/expected/schema_settings-openapi3.json b/schemars/tests/expected/schema_settings-openapi3.json
index 6ff2604..e5032f0 100644
--- a/schemars/tests/expected/schema_settings-openapi3.json
+++ b/schemars/tests/expected/schema_settings-openapi3.json
@@ -20,12 +20,32 @@
           "$ref": "#/components/schemas/Inner"
         }
       ]
+    },
+    "tuples": {
+      "type": "array",
+      "items": {
+        "type": "array",
+        "items": [
+          {
+            "type": "integer",
+            "format": "uint8",
+            "minimum": 0
+          },
+          {
+            "type": "integer",
+            "format": "int64"
+          }
+        ],
+        "minItems": 2,
+        "maxItems": 2
+      }
     }
   },
   "required": [
     "int",
     "values",
-    "value"
+    "value",
+    "tuples"
   ],
   "components": {
     "schemas": {
diff --git a/schemars/tests/expected/schema_settings.json b/schemars/tests/expected/schema_settings.json
index 4a50262..a836cd6 100644
--- a/schemars/tests/expected/schema_settings.json
+++ b/schemars/tests/expected/schema_settings.json
@@ -25,12 +25,32 @@
           "type": "null"
         }
       ]
+    },
+    "tuples": {
+      "type": "array",
+      "items": {
+        "type": "array",
+        "items": [
+          {
+            "type": "integer",
+            "format": "uint8",
+            "minimum": 0
+          },
+          {
+            "type": "integer",
+            "format": "int64"
+          }
+        ],
+        "minItems": 2,
+        "maxItems": 2
+      }
     }
   },
   "required": [
     "int",
     "values",
-    "value"
+    "value",
+    "tuples"
   ],
   "definitions": {
     "Inner": {
diff --git a/schemars/tests/expected/schema_with-enum-adjacent-tagged.json b/schemars/tests/expected/schema_with-enum-adjacent-tagged.json
index ab848e3..3e7173d 100644
--- a/schemars/tests/expected/schema_with-enum-adjacent-tagged.json
+++ b/schemars/tests/expected/schema_with-enum-adjacent-tagged.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Adjacent",
   "oneOf": [
     {
@@ -57,7 +57,7 @@
         },
         "c": {
           "type": "array",
-          "items": [
+          "prefixItems": [
             {
               "type": "boolean"
             },
diff --git a/schemars/tests/expected/schema_with-enum-external.json b/schemars/tests/expected/schema_with-enum-external.json
index 5f28d2f..5f5fe83 100644
--- a/schemars/tests/expected/schema_with-enum-external.json
+++ b/schemars/tests/expected/schema_with-enum-external.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "External",
   "oneOf": [
     {
@@ -39,7 +39,7 @@
       "properties": {
         "tuple": {
           "type": "array",
-          "items": [
+          "prefixItems": [
             {
               "type": "boolean"
             },
diff --git a/schemars/tests/expected/schema_with-enum-internal.json b/schemars/tests/expected/schema_with-enum-internal.json
index 90871ad..e6d707b 100644
--- a/schemars/tests/expected/schema_with-enum-internal.json
+++ b/schemars/tests/expected/schema_with-enum-internal.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Internal",
   "oneOf": [
     {
diff --git a/schemars/tests/expected/schema_with-enum-untagged.json b/schemars/tests/expected/schema_with-enum-untagged.json
index 834eb41..9057c87 100644
--- a/schemars/tests/expected/schema_with-enum-untagged.json
+++ b/schemars/tests/expected/schema_with-enum-untagged.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Untagged",
   "anyOf": [
     {
@@ -18,7 +18,7 @@
     },
     {
       "type": "array",
-      "items": [
+      "prefixItems": [
         {
           "type": "boolean"
         },
diff --git a/schemars/tests/expected/schema_with-newtype.json b/schemars/tests/expected/schema_with-newtype.json
index 8b709fb..eb4a2f6 100644
--- a/schemars/tests/expected/schema_with-newtype.json
+++ b/schemars/tests/expected/schema_with-newtype.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Newtype",
   "type": "boolean"
 }
\ No newline at end of file
diff --git a/schemars/tests/expected/schema_with-struct.json b/schemars/tests/expected/schema_with-struct.json
index 31caebe..0674f1e 100644
--- a/schemars/tests/expected/schema_with-struct.json
+++ b/schemars/tests/expected/schema_with-struct.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Struct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/schema_with-transparent-newtype.json b/schemars/tests/expected/schema_with-transparent-newtype.json
index 9f6afb3..2aeff68 100644
--- a/schemars/tests/expected/schema_with-transparent-newtype.json
+++ b/schemars/tests/expected/schema_with-transparent-newtype.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "schema_fn",
   "type": "boolean"
 }
\ No newline at end of file
diff --git a/schemars/tests/expected/schema_with-tuple.json b/schemars/tests/expected/schema_with-tuple.json
index 4e2c095..1296e33 100644
--- a/schemars/tests/expected/schema_with-tuple.json
+++ b/schemars/tests/expected/schema_with-tuple.json
@@ -1,8 +1,8 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Tuple",
   "type": "array",
-  "items": [
+  "prefixItems": [
     {
       "type": "boolean"
     },
diff --git a/schemars/tests/expected/semver.json b/schemars/tests/expected/semver.json
index e8c59b9..9f5b155 100644
--- a/schemars/tests/expected/semver.json
+++ b/schemars/tests/expected/semver.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "SemverTypes",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/skip_enum_variants.json b/schemars/tests/expected/skip_enum_variants.json
index d245734..bd3a893 100644
--- a/schemars/tests/expected/skip_enum_variants.json
+++ b/schemars/tests/expected/skip_enum_variants.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyEnum",
   "oneOf": [
     {
diff --git a/schemars/tests/expected/skip_struct_fields.json b/schemars/tests/expected/skip_struct_fields.json
index 48549ce..2a74c32 100644
--- a/schemars/tests/expected/skip_struct_fields.json
+++ b/schemars/tests/expected/skip_struct_fields.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "MyStruct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/skip_tuple_fields.json b/schemars/tests/expected/skip_tuple_fields.json
index 3cdce84..c3a4255 100644
--- a/schemars/tests/expected/skip_tuple_fields.json
+++ b/schemars/tests/expected/skip_tuple_fields.json
@@ -1,8 +1,8 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "TupleStruct",
   "type": "array",
-  "items": [
+  "prefixItems": [
     {
       "type": "number",
       "format": "float"
diff --git a/schemars/tests/expected/smallvec.json b/schemars/tests/expected/smallvec.json
index 7ce011d..be50ed7 100644
--- a/schemars/tests/expected/smallvec.json
+++ b/schemars/tests/expected/smallvec.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Array_of_string",
   "type": "array",
   "items": {
diff --git a/schemars/tests/expected/smol_str.json b/schemars/tests/expected/smol_str.json
index ad174d8..0604332 100644
--- a/schemars/tests/expected/smol_str.json
+++ b/schemars/tests/expected/smol_str.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "string",
   "type": "string"
 }
\ No newline at end of file
diff --git a/schemars/tests/expected/struct-newtype.json b/schemars/tests/expected/struct-newtype.json
index 284e47d..e7b1cba 100644
--- a/schemars/tests/expected/struct-newtype.json
+++ b/schemars/tests/expected/struct-newtype.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Newtype",
   "type": "integer",
   "format": "int32"
diff --git a/schemars/tests/expected/struct-normal-additional-properties.json b/schemars/tests/expected/struct-normal-additional-properties.json
index 529e2c4..2c55fb7 100644
--- a/schemars/tests/expected/struct-normal-additional-properties.json
+++ b/schemars/tests/expected/struct-normal-additional-properties.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Struct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/struct-normal.json b/schemars/tests/expected/struct-normal.json
index 3e73393..c49757c 100644
--- a/schemars/tests/expected/struct-normal.json
+++ b/schemars/tests/expected/struct-normal.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Struct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/struct-tuple.json b/schemars/tests/expected/struct-tuple.json
index c89e416..8960068 100644
--- a/schemars/tests/expected/struct-tuple.json
+++ b/schemars/tests/expected/struct-tuple.json
@@ -1,8 +1,8 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Tuple",
   "type": "array",
-  "items": [
+  "prefixItems": [
     {
       "type": "integer",
       "format": "int32"
diff --git a/schemars/tests/expected/struct-unit.json b/schemars/tests/expected/struct-unit.json
index 3252d20..46f6fcf 100644
--- a/schemars/tests/expected/struct-unit.json
+++ b/schemars/tests/expected/struct-unit.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Unit",
   "type": "null"
 }
\ No newline at end of file
diff --git a/schemars/tests/expected/transparent-struct.json b/schemars/tests/expected/transparent-struct.json
index 7fc1c32..2692069 100644
--- a/schemars/tests/expected/transparent-struct.json
+++ b/schemars/tests/expected/transparent-struct.json
@@ -1,12 +1,12 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "OuterStruct",
   "type": "object",
   "properties": {
     "inner": {
       "anyOf": [
         {
-          "$ref": "#/definitions/InnerStruct"
+          "$ref": "#/$defs/InnerStruct"
         },
         {
           "type": "null"
@@ -14,10 +14,10 @@
       ]
     }
   },
-  "definitions": {
+  "$defs": {
     "InnerStruct": {
       "type": "array",
-      "items": [
+      "prefixItems": [
         {
           "type": "string"
         },
diff --git a/schemars/tests/expected/url.json b/schemars/tests/expected/url.json
index 5722f9e..425bf85 100644
--- a/schemars/tests/expected/url.json
+++ b/schemars/tests/expected/url.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "UrlTypes",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/uuid.json b/schemars/tests/expected/uuid.json
index 8ba1a01..98ae408 100644
--- a/schemars/tests/expected/uuid.json
+++ b/schemars/tests/expected/uuid.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Uuid",
   "type": "string",
   "format": "uuid"
diff --git a/schemars/tests/expected/validate.json b/schemars/tests/expected/validate.json
index 04131ce..57c7f52 100644
--- a/schemars/tests/expected/validate.json
+++ b/schemars/tests/expected/validate.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Struct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/validate_inner.json b/schemars/tests/expected/validate_inner.json
index ba4ee9e..a77e0d7 100644
--- a/schemars/tests/expected/validate_inner.json
+++ b/schemars/tests/expected/validate_inner.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Struct",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/validate_newtype.json b/schemars/tests/expected/validate_newtype.json
index 89bec96..cd835f5 100644
--- a/schemars/tests/expected/validate_newtype.json
+++ b/schemars/tests/expected/validate_newtype.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "NewType",
   "type": "integer",
   "format": "uint8",
diff --git a/schemars/tests/expected/validate_schemars_attrs.json b/schemars/tests/expected/validate_schemars_attrs.json
index 4fdba53..5e7d31d 100644
--- a/schemars/tests/expected/validate_schemars_attrs.json
+++ b/schemars/tests/expected/validate_schemars_attrs.json
@@ -1,5 +1,5 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Struct2",
   "type": "object",
   "properties": {
diff --git a/schemars/tests/expected/validate_tuple.json b/schemars/tests/expected/validate_tuple.json
index 2a0e266..fa81224 100644
--- a/schemars/tests/expected/validate_tuple.json
+++ b/schemars/tests/expected/validate_tuple.json
@@ -1,8 +1,8 @@
 {
-  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
   "title": "Tuple",
   "type": "array",
-  "items": [
+  "prefixItems": [
     {
       "type": "integer",
       "format": "uint8",
diff --git a/schemars/tests/schema_settings.rs b/schemars/tests/schema_settings.rs
index a82570d..3fe489a 100644
--- a/schemars/tests/schema_settings.rs
+++ b/schemars/tests/schema_settings.rs
@@ -12,6 +12,7 @@ pub struct Outer {
     pub values: BTreeMap<&'static str, Value>,
     pub value: Value,
     pub inner: Option<Inner>,
+    pub tuples: Vec<(u8, i64)>,
 }
 
 #[derive(JsonSchema)]
@@ -39,6 +40,11 @@ fn schema_matches_2019_09() -> TestResult {
     test_generated_schema::<Outer>("schema_settings-2019_09", SchemaSettings::draft2019_09())
 }
 
+#[test]
+fn schema_matches_2020_12() -> TestResult {
+    test_generated_schema::<Outer>("schema_settings-2020_12", SchemaSettings::draft2020_12())
+}
+
 #[test]
 fn schema_matches_openapi3() -> TestResult {
     test_generated_schema::<Outer>("schema_settings-openapi3", SchemaSettings::openapi3())