diff --git a/CHANGELOG.md b/CHANGELOG.md index ca3c4e9..cd92389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## [0.6.0] - TBD ### Added: - 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` will no longer inline `T`'s schema when it should be referenceable. ## [0.5.1] - 2019-10-30 ### Fixed: diff --git a/schemars/src/json_schema_impls/core.rs b/schemars/src/json_schema_impls/core.rs index b4fe2b9..7e8479c 100644 --- a/schemars/src/json_schema_impls/core.rs +++ b/schemars/src/json_schema_impls/core.rs @@ -12,11 +12,7 @@ impl JsonSchema for Option { } fn json_schema(gen: &mut SchemaGenerator) -> Schema { - let mut schema = if gen.settings().option_nullable { - T::json_schema(gen) - } else { - gen.subschema_for::() - }; + let mut schema = gen.subschema_for::(); if gen.settings().option_add_null_type { schema = match schema { Schema::Bool(true) => Schema::Bool(true), @@ -38,7 +34,7 @@ impl JsonSchema for Option { } } if gen.settings().option_nullable { - let mut schema_obj: SchemaObject = schema.into(); + let mut schema_obj = gen.objectify(schema.into()); schema_obj .extensions .insert("nullable".to_owned(), json!(true)); @@ -108,7 +104,10 @@ impl JsonSchema for Bound { fn json_schema(gen: &mut SchemaGenerator) -> Schema { let mut included_schema = SchemaObject::default(); 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 .object() .properties @@ -116,7 +115,10 @@ impl JsonSchema for Bound { let mut excluded_schema = SchemaObject::default(); 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 .object() .properties @@ -127,7 +129,11 @@ impl JsonSchema for Bound { unbounded_schema.const_value = Some(json!("Unbounded")); 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() } } diff --git a/schemars/tests/expected/schema-openapi3.json b/schemars/tests/expected/schema-openapi3.json index b04b607..7833836 100644 --- a/schemars/tests/expected/schema-openapi3.json +++ b/schemars/tests/expected/schema-openapi3.json @@ -21,36 +21,18 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -77,18 +59,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -115,18 +88,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -156,33 +120,18 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true }, "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).", - "anyOf": [ + "allOf": [ { - "$ref": "#/components/schemas/Schema" - }, - { - "type": "array", - "items": { - "$ref": "#/components/schemas/Schema" - } + "$ref": "#/components/schemas/SingleOrVec_for_Schema" } ], "nullable": true @@ -249,18 +198,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -294,18 +234,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -323,18 +254,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -346,15 +268,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "$ref": "#/components/schemas/InstanceType" - }, - { - "type": "array", - "items": { - "$ref": "#/components/schemas/InstanceType" - } + "$ref": "#/components/schemas/SingleOrVec_for_InstanceType" } ], "nullable": true @@ -416,36 +332,18 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -472,18 +370,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -503,18 +392,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -544,33 +424,18 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true }, "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).", - "anyOf": [ + "allOf": [ { - "$ref": "#/components/schemas/Schema" - }, - { - "type": "array", - "items": { - "$ref": "#/components/schemas/Schema" - } + "$ref": "#/components/schemas/SingleOrVec_for_Schema" } ], "nullable": true @@ -637,18 +502,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -682,18 +538,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -711,18 +558,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "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": [ - { - "$ref": "#/components/schemas/SchemaObject" - } - ] + "$ref": "#/components/schemas/Schema" } ], "nullable": true @@ -734,15 +572,9 @@ }, "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).", - "anyOf": [ + "allOf": [ { - "$ref": "#/components/schemas/InstanceType" - }, - { - "type": "array", - "items": { - "$ref": "#/components/schemas/InstanceType" - } + "$ref": "#/components/schemas/SingleOrVec_for_InstanceType" } ], "nullable": true @@ -758,6 +590,34 @@ } }, "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" + } + } + ] } } } \ No newline at end of file