Do not inline referenceable schemas to set nullable

This commit is contained in:
Graham Esau 2019-12-08 11:29:02 +00:00
parent 529e3d4611
commit 89d3024beb
3 changed files with 85 additions and 217 deletions

View file

@ -3,6 +3,8 @@
## [0.6.0] - TBD ## [0.6.0] - TBD
### Added: ### Added:
- When deriving `JsonSchema`, the schema's `title` and `description` are now set from `#[doc]` comments (https://github.com/GREsau/schemars/issues/7) - When deriving `JsonSchema`, the schema's `title` and `description` are now set from `#[doc]` comments (https://github.com/GREsau/schemars/issues/7)
### Changed:
- When the `option_nullable` setting is enabled (e.g. for openapi 3), schemas for `Option<T>` will no longer inline `T`'s schema when it should be referenceable.
## [0.5.1] - 2019-10-30 ## [0.5.1] - 2019-10-30
### Fixed: ### Fixed:

View file

@ -12,11 +12,7 @@ impl<T: JsonSchema> JsonSchema for Option<T> {
} }
fn json_schema(gen: &mut SchemaGenerator) -> Schema { fn json_schema(gen: &mut SchemaGenerator) -> Schema {
let mut schema = if gen.settings().option_nullable { let mut schema = gen.subschema_for::<T>();
T::json_schema(gen)
} else {
gen.subschema_for::<T>()
};
if gen.settings().option_add_null_type { if gen.settings().option_add_null_type {
schema = match schema { schema = match schema {
Schema::Bool(true) => Schema::Bool(true), Schema::Bool(true) => Schema::Bool(true),
@ -38,7 +34,7 @@ impl<T: JsonSchema> JsonSchema for Option<T> {
} }
} }
if gen.settings().option_nullable { if gen.settings().option_nullable {
let mut schema_obj: SchemaObject = schema.into(); let mut schema_obj = gen.objectify(schema.into());
schema_obj schema_obj
.extensions .extensions
.insert("nullable".to_owned(), json!(true)); .insert("nullable".to_owned(), json!(true));
@ -108,7 +104,10 @@ impl<T: JsonSchema> JsonSchema for Bound<T> {
fn json_schema(gen: &mut SchemaGenerator) -> Schema { fn json_schema(gen: &mut SchemaGenerator) -> Schema {
let mut included_schema = SchemaObject::default(); let mut included_schema = SchemaObject::default();
included_schema.instance_type = Some(InstanceType::Object.into()); included_schema.instance_type = Some(InstanceType::Object.into());
included_schema.object().required.insert("Included".to_owned()); included_schema
.object()
.required
.insert("Included".to_owned());
included_schema included_schema
.object() .object()
.properties .properties
@ -116,7 +115,10 @@ impl<T: JsonSchema> JsonSchema for Bound<T> {
let mut excluded_schema = SchemaObject::default(); let mut excluded_schema = SchemaObject::default();
excluded_schema.instance_type = Some(InstanceType::Object.into()); excluded_schema.instance_type = Some(InstanceType::Object.into());
excluded_schema.object().required.insert("Excluded".to_owned()); excluded_schema
.object()
.required
.insert("Excluded".to_owned());
excluded_schema excluded_schema
.object() .object()
.properties .properties
@ -127,7 +129,11 @@ impl<T: JsonSchema> JsonSchema for Bound<T> {
unbounded_schema.const_value = Some(json!("Unbounded")); unbounded_schema.const_value = Some(json!("Unbounded"));
let mut schema = SchemaObject::default(); let mut schema = SchemaObject::default();
schema.subschemas().one_of = Some(vec![included_schema.into(), excluded_schema.into(), unbounded_schema.into()]); schema.subschemas().one_of = Some(vec![
included_schema.into(),
excluded_schema.into(),
unbounded_schema.into(),
]);
schema.into() schema.into()
} }
} }

View file

@ -21,36 +21,18 @@
}, },
"additionalItems": { "additionalItems": {
"description": "The `additionalItems` keyword.\n\nSee [JSON Schema 9.3.1.2. \"additionalItems\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.2).", "description": "The `additionalItems` keyword.\n\nSee [JSON Schema 9.3.1.2. \"additionalItems\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.2).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
}, },
"additionalProperties": { "additionalProperties": {
"description": "The `additionalProperties` keyword.\n\nSee [JSON Schema 9.3.2.3. \"additionalProperties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.3).", "description": "The `additionalProperties` keyword.\n\nSee [JSON Schema 9.3.2.3. \"additionalProperties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.3).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -77,18 +59,9 @@
}, },
"contains": { "contains": {
"description": "The `contains` keyword.\n\nSee [JSON Schema 9.3.1.4. \"contains\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.4).", "description": "The `contains` keyword.\n\nSee [JSON Schema 9.3.1.4. \"contains\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.4).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -115,18 +88,9 @@
}, },
"else": { "else": {
"description": "The `else` keyword.\n\nSee [JSON Schema 9.2.2.3. \"else\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.3).", "description": "The `else` keyword.\n\nSee [JSON Schema 9.2.2.3. \"else\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.3).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -156,33 +120,18 @@
}, },
"if": { "if": {
"description": "The `if` keyword.\n\nSee [JSON Schema 9.2.2.1. \"if\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.1).", "description": "The `if` keyword.\n\nSee [JSON Schema 9.2.2.1. \"if\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.1).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
}, },
"items": { "items": {
"description": "The `items` keyword.\n\nSee [JSON Schema 9.3.1.1. \"items\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.1).", "description": "The `items` keyword.\n\nSee [JSON Schema 9.3.1.1. \"items\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.1).",
"anyOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/Schema" "$ref": "#/components/schemas/SingleOrVec_for_Schema"
},
{
"type": "array",
"items": {
"$ref": "#/components/schemas/Schema"
}
} }
], ],
"nullable": true "nullable": true
@ -249,18 +198,9 @@
}, },
"not": { "not": {
"description": "The `not` keyword.\n\nSee [JSON Schema 9.2.1.4. \"not\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.4).", "description": "The `not` keyword.\n\nSee [JSON Schema 9.2.1.4. \"not\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.4).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -294,18 +234,9 @@
}, },
"propertyNames": { "propertyNames": {
"description": "The `propertyNames` keyword.\n\nSee [JSON Schema 9.3.2.5. \"propertyNames\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.5).", "description": "The `propertyNames` keyword.\n\nSee [JSON Schema 9.3.2.5. \"propertyNames\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.5).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -323,18 +254,9 @@
}, },
"then": { "then": {
"description": "The `then` keyword.\n\nSee [JSON Schema 9.2.2.2. \"then\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.2).", "description": "The `then` keyword.\n\nSee [JSON Schema 9.2.2.2. \"then\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.2).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -346,15 +268,9 @@
}, },
"type": { "type": {
"description": "The `type` keyword.\n\nSee [JSON Schema Validation 6.1.1. \"type\"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.1) and [JSON Schema 4.2.1. Instance Data Model](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-4.2.1).", "description": "The `type` keyword.\n\nSee [JSON Schema Validation 6.1.1. \"type\"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.1) and [JSON Schema 4.2.1. Instance Data Model](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-4.2.1).",
"anyOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/InstanceType" "$ref": "#/components/schemas/SingleOrVec_for_InstanceType"
},
{
"type": "array",
"items": {
"$ref": "#/components/schemas/InstanceType"
}
} }
], ],
"nullable": true "nullable": true
@ -416,36 +332,18 @@
}, },
"additionalItems": { "additionalItems": {
"description": "The `additionalItems` keyword.\n\nSee [JSON Schema 9.3.1.2. \"additionalItems\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.2).", "description": "The `additionalItems` keyword.\n\nSee [JSON Schema 9.3.1.2. \"additionalItems\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.2).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
}, },
"additionalProperties": { "additionalProperties": {
"description": "The `additionalProperties` keyword.\n\nSee [JSON Schema 9.3.2.3. \"additionalProperties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.3).", "description": "The `additionalProperties` keyword.\n\nSee [JSON Schema 9.3.2.3. \"additionalProperties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.3).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -472,18 +370,9 @@
}, },
"contains": { "contains": {
"description": "The `contains` keyword.\n\nSee [JSON Schema 9.3.1.4. \"contains\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.4).", "description": "The `contains` keyword.\n\nSee [JSON Schema 9.3.1.4. \"contains\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.4).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -503,18 +392,9 @@
}, },
"else": { "else": {
"description": "The `else` keyword.\n\nSee [JSON Schema 9.2.2.3. \"else\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.3).", "description": "The `else` keyword.\n\nSee [JSON Schema 9.2.2.3. \"else\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.3).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -544,33 +424,18 @@
}, },
"if": { "if": {
"description": "The `if` keyword.\n\nSee [JSON Schema 9.2.2.1. \"if\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.1).", "description": "The `if` keyword.\n\nSee [JSON Schema 9.2.2.1. \"if\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.1).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
}, },
"items": { "items": {
"description": "The `items` keyword.\n\nSee [JSON Schema 9.3.1.1. \"items\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.1).", "description": "The `items` keyword.\n\nSee [JSON Schema 9.3.1.1. \"items\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.1).",
"anyOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/Schema" "$ref": "#/components/schemas/SingleOrVec_for_Schema"
},
{
"type": "array",
"items": {
"$ref": "#/components/schemas/Schema"
}
} }
], ],
"nullable": true "nullable": true
@ -637,18 +502,9 @@
}, },
"not": { "not": {
"description": "The `not` keyword.\n\nSee [JSON Schema 9.2.1.4. \"not\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.4).", "description": "The `not` keyword.\n\nSee [JSON Schema 9.2.1.4. \"not\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.4).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -682,18 +538,9 @@
}, },
"propertyNames": { "propertyNames": {
"description": "The `propertyNames` keyword.\n\nSee [JSON Schema 9.3.2.5. \"propertyNames\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.5).", "description": "The `propertyNames` keyword.\n\nSee [JSON Schema 9.3.2.5. \"propertyNames\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.5).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -711,18 +558,9 @@
}, },
"then": { "then": {
"description": "The `then` keyword.\n\nSee [JSON Schema 9.2.2.2. \"then\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.2).", "description": "The `then` keyword.\n\nSee [JSON Schema 9.2.2.2. \"then\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.2).",
"anyOf": [
{
"description": "A trivial boolean JSON Schema.\n\nThe schema `true` matches everything (always passes validation), whereas the schema `false` matches nothing (always fails validation).",
"type": "boolean"
},
{
"description": "A JSON Schema object.",
"allOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/SchemaObject" "$ref": "#/components/schemas/Schema"
}
]
} }
], ],
"nullable": true "nullable": true
@ -734,15 +572,9 @@
}, },
"type": { "type": {
"description": "The `type` keyword.\n\nSee [JSON Schema Validation 6.1.1. \"type\"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.1) and [JSON Schema 4.2.1. Instance Data Model](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-4.2.1).", "description": "The `type` keyword.\n\nSee [JSON Schema Validation 6.1.1. \"type\"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.1) and [JSON Schema 4.2.1. Instance Data Model](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-4.2.1).",
"anyOf": [ "allOf": [
{ {
"$ref": "#/components/schemas/InstanceType" "$ref": "#/components/schemas/SingleOrVec_for_InstanceType"
},
{
"type": "array",
"items": {
"$ref": "#/components/schemas/InstanceType"
}
} }
], ],
"nullable": true "nullable": true
@ -758,6 +590,34 @@
} }
}, },
"additionalProperties": true "additionalProperties": true
},
"SingleOrVec_for_InstanceType": {
"description": "A type which can be serialized as a single item, or multiple items.\n\nIn some contexts, a `Single` may be semantically distinct from a `Vec` containing only item.",
"anyOf": [
{
"$ref": "#/components/schemas/InstanceType"
},
{
"type": "array",
"items": {
"$ref": "#/components/schemas/InstanceType"
}
}
]
},
"SingleOrVec_for_Schema": {
"description": "A type which can be serialized as a single item, or multiple items.\n\nIn some contexts, a `Single` may be semantically distinct from a `Vec` containing only item.",
"anyOf": [
{
"$ref": "#/components/schemas/Schema"
},
{
"type": "array",
"items": {
"$ref": "#/components/schemas/Schema"
}
}
]
} }
} }
} }