From 8ec3016ee731ebbd933367c4320282acb9b42959 Mon Sep 17 00:00:00 2001 From: Romain Lebran Date: Sat, 29 Jun 2024 13:04:21 +0200 Subject: [PATCH 1/2] Fix add title for enums --- .../src/tests/api_component_derive_oas_3_1.rs | 2 + apistos-models/Cargo.toml | 3 + apistos-models/src/schema.rs | 316 ++++++++++++++++++ 3 files changed, 321 insertions(+) diff --git a/apistos-gen-test/src/tests/api_component_derive_oas_3_1.rs b/apistos-gen-test/src/tests/api_component_derive_oas_3_1.rs index 21578ceb..44a347ec 100644 --- a/apistos-gen-test/src/tests/api_component_derive_oas_3_1.rs +++ b/apistos-gen-test/src/tests/api_component_derive_oas_3_1.rs @@ -876,6 +876,7 @@ fn api_component_derive_named_enums_deep() { json!({ "oneOf": [ { + "title": "something", "type": "object", "properties": { "type": { @@ -892,6 +893,7 @@ fn api_component_derive_named_enums_deep() { ] }, { + "title": "other", "type": "object", "properties": { "type": { diff --git a/apistos-models/Cargo.toml b/apistos-models/Cargo.toml index b183e0d9..1e30cb9a 100644 --- a/apistos-models/Cargo.toml +++ b/apistos-models/Cargo.toml @@ -20,6 +20,9 @@ serde = { workspace = true } serde_json = { workspace = true } log = { workspace = true } +[dev-dependencies] +assert-json-diff = { workspace = true } + [features] deserialize = [] test = [] diff --git a/apistos-models/src/schema.rs b/apistos-models/src/schema.rs index 986ca3f0..741748b9 100644 --- a/apistos-models/src/schema.rs +++ b/apistos-models/src/schema.rs @@ -85,6 +85,10 @@ impl ApistosSchema { sch_obj.entry("title").or_insert_with(|| prop_name.clone().into()); } } + } else if let Some(_type) = props.get("type").and_then(|v| v.as_object()) { + if let Some(Value::String(prop_name)) = _type.get("const") { + sch_obj.entry("title").or_insert_with(|| prop_name.clone().into()); + } } } else if let Some(enum_values) = sch_obj.clone().get_mut("enum").and_then(|v| v.as_array_mut()) { if enum_values.len() == 1 { @@ -111,3 +115,315 @@ impl From for crate::reference_or::ReferenceOr { Self::Object(value.into()) } } + +#[cfg(test)] +mod test { + use assert_json_diff::assert_json_eq; + + use crate::{ApistosSchema, JsonSchema, OpenApiVersion}; + use schemars::gen::SchemaSettings; + use serde::Serialize; + use serde_json::json; + + #[test] + fn test_apistos_schema_transform_3_0() { + #[derive(JsonSchema, Serialize)] + struct Test { + name: String, + } + + #[derive(JsonSchema, Serialize)] + struct Test2 { + surname: String, + } + + #[derive(JsonSchema)] + enum TestEnum { + Test, + Test2, + } + + #[derive(JsonSchema, Serialize)] + #[serde(tag = "type")] + enum TestAlgebraicEnum { + Test { key: String, value: String }, + Test2 { key2: String, value2: String }, + } + + #[derive(JsonSchema, Serialize)] + #[serde(tag = "type")] + enum TestAlgebraicEnum2 { + Test(Test), + Test2(Test2), + } + + let mut gen = SchemaSettings::openapi3().into_generator(); + let schema = TestEnum::json_schema(&mut gen); + + let apistos_schema = ApistosSchema::new(schema, OpenApiVersion::OAS3_0); + + assert_json_eq!( + apistos_schema.into_inner(), + json!({ + "type": "string", + "enum": [ + "Test", + "Test2" + ] + }) + ); + + let mut gen = SchemaSettings::openapi3().into_generator(); + let schema = TestAlgebraicEnum::json_schema(&mut gen); + + let apistos_schema = ApistosSchema::new(schema, OpenApiVersion::OAS3_0); + + assert_json_eq!( + apistos_schema.into_inner(), + json!({ + "oneOf": [ + { + "title": "Test", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Test" + }, + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "type", + "key", + "value" + ] + }, + { + "title": "Test2", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Test2" + }, + "key2": { + "type": "string" + }, + "value2": { + "type": "string" + } + }, + "required": [ + "type", + "key2", + "value2" + ] + } + ] + }) + ); + + let mut gen = SchemaSettings::openapi3().into_generator(); + let schema = TestAlgebraicEnum2::json_schema(&mut gen); + + let apistos_schema = ApistosSchema::new(schema, OpenApiVersion::OAS3_0); + + assert_json_eq!( + apistos_schema.into_inner(), + json!({ + "oneOf": [ + { + "title": "Test", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Test" + }, + "name": { + "type": "string" + } + }, + "required": [ + "type", + "name" + ] + }, + { + "title": "Test2", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Test2" + }, + "surname": { + "type": "string" + } + }, + "required": [ + "type", + "surname" + ] + } + ] + }) + ); + } + + #[test] + fn test_apistos_schema_transform_3_1() { + #[derive(JsonSchema, Serialize)] + struct Test { + name: String, + } + + #[derive(JsonSchema, Serialize)] + struct Test2 { + surname: String, + } + + #[derive(JsonSchema)] + enum TestEnum { + Test, + Test2, + } + + #[derive(JsonSchema, Serialize)] + #[serde(tag = "type")] + enum TestAlgebraicEnum { + Test { key: String, value: String }, + Test2 { key2: String, value2: String }, + } + + #[derive(JsonSchema, Serialize)] + #[serde(tag = "type")] + enum TestAlgebraicEnum2 { + Test(Test), + Test2(Test2), + } + + let mut gen = SchemaSettings::draft2020_12().into_generator(); + let schema = TestEnum::json_schema(&mut gen); + + let apistos_schema = ApistosSchema::new(schema, OpenApiVersion::OAS3_1); + + assert_json_eq!( + apistos_schema.into_inner(), + json!({ + "type": "string", + "enum": [ + "Test", + "Test2" + ] + }) + ); + + let mut gen = SchemaSettings::draft2020_12().into_generator(); + let schema = TestAlgebraicEnum::json_schema(&mut gen); + + let apistos_schema = ApistosSchema::new(schema, OpenApiVersion::OAS3_1); + + assert_json_eq!( + apistos_schema.into_inner(), + json!({ + "oneOf": [ + { + "title": "Test", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Test" + }, + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "type", + "key", + "value" + ] + }, + { + "title": "Test2", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Test2" + }, + "key2": { + "type": "string" + }, + "value2": { + "type": "string" + } + }, + "required": [ + "type", + "key2", + "value2" + ] + } + ] + }) + ); + + let mut gen = SchemaSettings::draft2020_12().into_generator(); + let schema = TestAlgebraicEnum2::json_schema(&mut gen); + + let apistos_schema = ApistosSchema::new(schema, OpenApiVersion::OAS3_1); + + assert_json_eq!( + apistos_schema.into_inner(), + json!({ + "oneOf": [ + { + "title": "Test", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Test" + }, + "name": { + "type": "string" + } + }, + "required": [ + "type", + "name" + ] + }, + { + "title": "Test2", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "Test2" + }, + "surname": { + "type": "string" + } + }, + "required": [ + "type", + "surname" + ] + } + ] + }) + ) + } +} From a9ad7259bf000e20b4ba91a208f8bfe66a02e689 Mon Sep 17 00:00:00 2001 From: Romain Lebran Date: Sat, 29 Jun 2024 13:09:16 +0200 Subject: [PATCH 2/2] Fix clippy --- apistos-models/src/schema.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/apistos-models/src/schema.rs b/apistos-models/src/schema.rs index 741748b9..8471d82e 100644 --- a/apistos-models/src/schema.rs +++ b/apistos-models/src/schema.rs @@ -126,14 +126,15 @@ mod test { use serde_json::json; #[test] + #[allow(dead_code, unused_qualifications)] fn test_apistos_schema_transform_3_0() { #[derive(JsonSchema, Serialize)] - struct Test { + struct TestStruct { name: String, } #[derive(JsonSchema, Serialize)] - struct Test2 { + struct TestStruct2 { surname: String, } @@ -153,8 +154,8 @@ mod test { #[derive(JsonSchema, Serialize)] #[serde(tag = "type")] enum TestAlgebraicEnum2 { - Test(Test), - Test2(Test2), + Test(TestStruct), + Test2(TestStruct2), } let mut gen = SchemaSettings::openapi3().into_generator(); @@ -277,14 +278,15 @@ mod test { } #[test] + #[allow(dead_code, unused_qualifications)] fn test_apistos_schema_transform_3_1() { #[derive(JsonSchema, Serialize)] - struct Test { + struct TestStruct { name: String, } #[derive(JsonSchema, Serialize)] - struct Test2 { + struct TestStruct2 { surname: String, } @@ -304,8 +306,8 @@ mod test { #[derive(JsonSchema, Serialize)] #[serde(tag = "type")] enum TestAlgebraicEnum2 { - Test(Test), - Test2(Test2), + Test(TestStruct), + Test2(TestStruct2), } let mut gen = SchemaSettings::draft2020_12().into_generator();