Simplify schema for Options

This commit is contained in:
Graham Esau 2019-09-14 22:44:05 +01:00
parent d7a214526f
commit 13267d37d7
3 changed files with 144 additions and 192 deletions

View file

@ -20,6 +20,12 @@ impl<T: JsonSchema> JsonSchema for Option<T> {
schema = match schema { schema = match schema {
Schema::Bool(true) => Schema::Bool(true), Schema::Bool(true) => Schema::Bool(true),
Schema::Bool(false) => <()>::json_schema(gen)?, Schema::Bool(false) => <()>::json_schema(gen)?,
Schema::Object(
obj @ SchemaObject {
instance_type: Some(_),
..
},
) => Schema::Object(with_null_type(obj)),
schema => SchemaObject { schema => SchemaObject {
any_of: Some(vec![schema, <()>::json_schema(gen)?]), any_of: Some(vec![schema, <()>::json_schema(gen)?]),
..Default::default() ..Default::default()
@ -36,6 +42,20 @@ impl<T: JsonSchema> JsonSchema for Option<T> {
} }
} }
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<T: ?Sized> JsonSchema for std::marker::PhantomData<T> { impl<T: ?Sized> JsonSchema for std::marker::PhantomData<T> {
no_ref_schema!(); no_ref_schema!();
@ -70,12 +90,32 @@ mod tests {
#[test] #[test]
fn schema_for_option() { fn schema_for_option() {
let schema = schema_object_for::<Option<i32>>(); let schema = schema_object_for::<Option<i32>>();
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::<Option<Foo>>();
assert_eq!(schema.instance_type, None); assert_eq!(schema.instance_type, None);
assert_eq!(schema.extensions.get("nullable"), None); assert_eq!(schema.extensions.get("nullable"), None);
assert_eq!(schema.any_of.is_some(), true); assert_eq!(schema.any_of.is_some(), true);
let any_of = schema.any_of.unwrap(); let any_of = schema.any_of.unwrap();
assert_eq!(any_of.len(), 2); assert_eq!(any_of.len(), 2);
assert_eq!(any_of[0], schema_for::<i32>()); assert_eq!(
any_of[0],
Schema::Ref(Ref {
reference: "#/definitions/Foo".to_string()
})
);
assert_eq!(any_of[1], schema_for::<()>()); assert_eq!(any_of[1], schema_for::<()>());
} }

View file

@ -144,7 +144,7 @@ pub struct ObjectValidation {
pub property_names: Option<Box<Schema>>, pub property_names: Option<Box<Schema>>,
} }
#[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")] #[serde(rename_all = "camelCase")]
pub enum InstanceType { pub enum InstanceType {
Null, Null,

View file

@ -52,23 +52,15 @@
"type": "object", "type": "object",
"properties": { "properties": {
"$id": { "$id": {
"anyOf": [ "type": [
{ "string",
"type": "string" "null"
},
{
"type": "null"
}
] ]
}, },
"$schema": { "$schema": {
"anyOf": [ "type": [
{ "string",
"type": "string" "null"
},
{
"type": "null"
}
] ]
}, },
"additionalItems": { "additionalItems": {
@ -92,30 +84,22 @@
] ]
}, },
"allOf": { "allOf": {
"anyOf": [ "type": [
{ "array",
"type": "array", "null"
"items": { ],
"$ref": "#/definitions/Schema" "items": {
} "$ref": "#/definitions/Schema"
}, }
{
"type": "null"
}
]
}, },
"anyOf": { "anyOf": {
"anyOf": [ "type": [
{ "array",
"type": "array", "null"
"items": { ],
"$ref": "#/definitions/Schema" "items": {
} "$ref": "#/definitions/Schema"
}, }
{
"type": "null"
}
]
}, },
"const": true, "const": true,
"contains": { "contains": {
@ -135,13 +119,9 @@
} }
}, },
"description": { "description": {
"anyOf": [ "type": [
{ "string",
"type": "string" "null"
},
{
"type": "null"
}
] ]
}, },
"else": { "else": {
@ -155,46 +135,30 @@
] ]
}, },
"enum": { "enum": {
"anyOf": [ "type": [
{ "array",
"type": "array", "null"
"items": true ],
}, "items": true
{
"type": "null"
}
]
}, },
"exclusiveMaximum": { "exclusiveMaximum": {
"anyOf": [ "type": [
{ "number",
"type": "number", "null"
"format": "double" ],
}, "format": "double"
{
"type": "null"
}
]
}, },
"exclusiveMinimum": { "exclusiveMinimum": {
"anyOf": [ "type": [
{ "number",
"type": "number", "null"
"format": "double" ],
}, "format": "double"
{
"type": "null"
}
]
}, },
"format": { "format": {
"anyOf": [ "type": [
{ "string",
"type": "string" "null"
},
{
"type": "null"
}
] ]
}, },
"if": { "if": {
@ -218,103 +182,67 @@
] ]
}, },
"maxItems": { "maxItems": {
"anyOf": [ "type": [
{ "integer",
"type": "integer", "null"
"format": "uint32" ],
}, "format": "uint32"
{
"type": "null"
}
]
}, },
"maxLength": { "maxLength": {
"anyOf": [ "type": [
{ "integer",
"type": "integer", "null"
"format": "uint32" ],
}, "format": "uint32"
{
"type": "null"
}
]
}, },
"maxProperties": { "maxProperties": {
"anyOf": [ "type": [
{ "integer",
"type": "integer", "null"
"format": "uint32" ],
}, "format": "uint32"
{
"type": "null"
}
]
}, },
"maximum": { "maximum": {
"anyOf": [ "type": [
{ "number",
"type": "number", "null"
"format": "double" ],
}, "format": "double"
{
"type": "null"
}
]
}, },
"minItems": { "minItems": {
"anyOf": [ "type": [
{ "integer",
"type": "integer", "null"
"format": "uint32" ],
}, "format": "uint32"
{
"type": "null"
}
]
}, },
"minLength": { "minLength": {
"anyOf": [ "type": [
{ "integer",
"type": "integer", "null"
"format": "uint32" ],
}, "format": "uint32"
{
"type": "null"
}
]
}, },
"minProperties": { "minProperties": {
"anyOf": [ "type": [
{ "integer",
"type": "integer", "null"
"format": "uint32" ],
}, "format": "uint32"
{
"type": "null"
}
]
}, },
"minimum": { "minimum": {
"anyOf": [ "type": [
{ "number",
"type": "number", "null"
"format": "double" ],
}, "format": "double"
{
"type": "null"
}
]
}, },
"multipleOf": { "multipleOf": {
"anyOf": [ "type": [
{ "number",
"type": "number", "null"
"format": "double" ],
}, "format": "double"
{
"type": "null"
}
]
}, },
"not": { "not": {
"anyOf": [ "anyOf": [
@ -327,26 +255,18 @@
] ]
}, },
"oneOf": { "oneOf": {
"anyOf": [ "type": [
{ "array",
"type": "array", "null"
"items": { ],
"$ref": "#/definitions/Schema" "items": {
} "$ref": "#/definitions/Schema"
}, }
{
"type": "null"
}
]
}, },
"pattern": { "pattern": {
"anyOf": [ "type": [
{ "string",
"type": "string" "null"
},
{
"type": "null"
}
] ]
}, },
"patternProperties": { "patternProperties": {
@ -388,13 +308,9 @@
] ]
}, },
"title": { "title": {
"anyOf": [ "type": [
{ "string",
"type": "string" "null"
},
{
"type": "null"
}
] ]
}, },
"type": { "type": {
@ -408,13 +324,9 @@
] ]
}, },
"uniqueItems": { "uniqueItems": {
"anyOf": [ "type": [
{ "boolean",
"type": "boolean" "null"
},
{
"type": "null"
}
] ]
} }
}, },