From 13267d37d74030c589f2c846b0dbee32edb0d5ec Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Sat, 14 Sep 2019 22:44:05 +0100 Subject: [PATCH] Simplify schema for Options --- schemars/src/json_schema_impls/core.rs | 42 +++- schemars/src/schema.rs | 2 +- schemars/tests/expected/schema.json | 292 +++++++++---------------- 3 files changed, 144 insertions(+), 192 deletions(-) diff --git a/schemars/src/json_schema_impls/core.rs b/schemars/src/json_schema_impls/core.rs index e3f50ab..e4bedc0 100644 --- a/schemars/src/json_schema_impls/core.rs +++ b/schemars/src/json_schema_impls/core.rs @@ -20,6 +20,12 @@ impl JsonSchema for Option { schema = match schema { Schema::Bool(true) => Schema::Bool(true), Schema::Bool(false) => <()>::json_schema(gen)?, + Schema::Object( + obj @ SchemaObject { + instance_type: Some(_), + .. + }, + ) => Schema::Object(with_null_type(obj)), schema => SchemaObject { any_of: Some(vec![schema, <()>::json_schema(gen)?]), ..Default::default() @@ -36,6 +42,20 @@ impl JsonSchema for Option { } } +fn with_null_type(mut obj: SchemaObject) -> SchemaObject { + match obj + .instance_type + .as_mut() + .expect("checked in calling function") + { + SingleOrVec::Single(ty) if **ty == InstanceType::Null => {} + SingleOrVec::Vec(ty) if ty.contains(&InstanceType::Null) => {} + SingleOrVec::Single(ty) => obj.instance_type = Some(vec![**ty, InstanceType::Null].into()), + SingleOrVec::Vec(ref mut ty) => ty.push(InstanceType::Null), + }; + obj +} + impl JsonSchema for std::marker::PhantomData { no_ref_schema!(); @@ -70,12 +90,32 @@ mod tests { #[test] fn schema_for_option() { let schema = schema_object_for::>(); + assert_eq!( + schema.instance_type, + Some(vec![InstanceType::Integer, InstanceType::Null].into()) + ); + assert_eq!(schema.extensions.get("nullable"), None); + assert_eq!(schema.any_of.is_none(), true); + } + + #[test] + fn schema_for_option_with_ref() { + use crate as schemars; + #[derive(JsonSchema)] + struct Foo; + + let schema = schema_object_for::>(); assert_eq!(schema.instance_type, None); assert_eq!(schema.extensions.get("nullable"), None); assert_eq!(schema.any_of.is_some(), true); let any_of = schema.any_of.unwrap(); assert_eq!(any_of.len(), 2); - assert_eq!(any_of[0], schema_for::()); + assert_eq!( + any_of[0], + Schema::Ref(Ref { + reference: "#/definitions/Foo".to_string() + }) + ); assert_eq!(any_of[1], schema_for::<()>()); } diff --git a/schemars/src/schema.rs b/schemars/src/schema.rs index 3074c51..c6ae2dd 100644 --- a/schemars/src/schema.rs +++ b/schemars/src/schema.rs @@ -144,7 +144,7 @@ pub struct ObjectValidation { pub property_names: Option>, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, JsonSchema)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, JsonSchema)] #[serde(rename_all = "camelCase")] pub enum InstanceType { Null, diff --git a/schemars/tests/expected/schema.json b/schemars/tests/expected/schema.json index 4c84b1d..2256828 100644 --- a/schemars/tests/expected/schema.json +++ b/schemars/tests/expected/schema.json @@ -52,23 +52,15 @@ "type": "object", "properties": { "$id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "$schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "additionalItems": { @@ -92,30 +84,22 @@ ] }, "allOf": { - "anyOf": [ - { - "type": "array", - "items": { - "$ref": "#/definitions/Schema" - } - }, - { - "type": "null" - } - ] + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Schema" + } }, "anyOf": { - "anyOf": [ - { - "type": "array", - "items": { - "$ref": "#/definitions/Schema" - } - }, - { - "type": "null" - } - ] + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Schema" + } }, "const": true, "contains": { @@ -135,13 +119,9 @@ } }, "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "else": { @@ -155,46 +135,30 @@ ] }, "enum": { - "anyOf": [ - { - "type": "array", - "items": true - }, - { - "type": "null" - } - ] + "type": [ + "array", + "null" + ], + "items": true }, "exclusiveMaximum": { - "anyOf": [ - { - "type": "number", - "format": "double" - }, - { - "type": "null" - } - ] + "type": [ + "number", + "null" + ], + "format": "double" }, "exclusiveMinimum": { - "anyOf": [ - { - "type": "number", - "format": "double" - }, - { - "type": "null" - } - ] + "type": [ + "number", + "null" + ], + "format": "double" }, "format": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "if": { @@ -218,103 +182,67 @@ ] }, "maxItems": { - "anyOf": [ - { - "type": "integer", - "format": "uint32" - }, - { - "type": "null" - } - ] + "type": [ + "integer", + "null" + ], + "format": "uint32" }, "maxLength": { - "anyOf": [ - { - "type": "integer", - "format": "uint32" - }, - { - "type": "null" - } - ] + "type": [ + "integer", + "null" + ], + "format": "uint32" }, "maxProperties": { - "anyOf": [ - { - "type": "integer", - "format": "uint32" - }, - { - "type": "null" - } - ] + "type": [ + "integer", + "null" + ], + "format": "uint32" }, "maximum": { - "anyOf": [ - { - "type": "number", - "format": "double" - }, - { - "type": "null" - } - ] + "type": [ + "number", + "null" + ], + "format": "double" }, "minItems": { - "anyOf": [ - { - "type": "integer", - "format": "uint32" - }, - { - "type": "null" - } - ] + "type": [ + "integer", + "null" + ], + "format": "uint32" }, "minLength": { - "anyOf": [ - { - "type": "integer", - "format": "uint32" - }, - { - "type": "null" - } - ] + "type": [ + "integer", + "null" + ], + "format": "uint32" }, "minProperties": { - "anyOf": [ - { - "type": "integer", - "format": "uint32" - }, - { - "type": "null" - } - ] + "type": [ + "integer", + "null" + ], + "format": "uint32" }, "minimum": { - "anyOf": [ - { - "type": "number", - "format": "double" - }, - { - "type": "null" - } - ] + "type": [ + "number", + "null" + ], + "format": "double" }, "multipleOf": { - "anyOf": [ - { - "type": "number", - "format": "double" - }, - { - "type": "null" - } - ] + "type": [ + "number", + "null" + ], + "format": "double" }, "not": { "anyOf": [ @@ -327,26 +255,18 @@ ] }, "oneOf": { - "anyOf": [ - { - "type": "array", - "items": { - "$ref": "#/definitions/Schema" - } - }, - { - "type": "null" - } - ] + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Schema" + } }, "pattern": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "patternProperties": { @@ -388,13 +308,9 @@ ] }, "title": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "type": { @@ -408,13 +324,9 @@ ] }, "uniqueItems": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } + "type": [ + "boolean", + "null" ] } },