From bbf32a850b8640d601fc2f0caf3d47775a646274 Mon Sep 17 00:00:00 2001 From: Kacper Stasik Date: Mon, 11 Sep 2023 20:45:39 +0200 Subject: [PATCH] fix: better models of oneOf - support for simple types --- crates/cli/src/commands/codegen.rs | 8 ++--- crates/cli/src/commands/validate.rs | 8 ++--- .../src/codegen/jsonschema/oneof/extractor.rs | 21 +++++++++--- .../src/codegen/jsonschema/oneof/mod.rs | 32 ++++++++++++++++--- .../src/codegen/jsonschema/required.rs | 2 +- .../src/codegen/jsonschema/types.rs | 2 +- .../src/codegen/openapi/endpoint.rs | 4 +-- crates/schematools/src/codegen/openapi/mod.rs | 4 +-- .../src/codegen/openapi/security.rs | 4 +-- crates/schematools/src/process/dereference.rs | 2 +- 10 files changed, 61 insertions(+), 26 deletions(-) diff --git a/crates/cli/src/commands/codegen.rs b/crates/cli/src/commands/codegen.rs index b49cbce..486dbc1 100644 --- a/crates/cli/src/commands/codegen.rs +++ b/crates/cli/src/commands/codegen.rs @@ -148,7 +148,7 @@ impl GetSchemaCommand for Opts { impl Opts { pub fn run( &self, - schema: &mut Schema, + schema: &Schema, discovery: &Discovery, storage: &SchemaStorage, ) -> Result<(), Error> { @@ -241,7 +241,7 @@ impl Opts { } pub fn execute(opts: Opts, client: &Client) -> Result<(), Error> { - let mut schema = opts.get_schema(client)?; + let schema = opts.get_schema(client)?; let storage = &SchemaStorage::new(&schema, client); let discovery = Discovery::default(); @@ -249,12 +249,12 @@ pub fn execute(opts: Opts, client: &Client) -> Result<(), Error> { Command::JsonSchema(o) => { o.verbose.start()?; - opts.run(&mut schema, &discovery, storage) + opts.run(&schema, &discovery, storage) } Command::Openapi(o) => { o.verbose.start()?; - opts.run(&mut schema, &discovery, storage) + opts.run(&schema, &discovery, storage) } } } diff --git a/crates/cli/src/commands/validate.rs b/crates/cli/src/commands/validate.rs index a027876..bcb2559 100644 --- a/crates/cli/src/commands/validate.rs +++ b/crates/cli/src/commands/validate.rs @@ -77,7 +77,7 @@ impl GetSchemaCommand for Opts { } impl Opts { - pub fn run(&self, schema: &mut Schema) -> Result<(), Error> { + pub fn run(&self, schema: &Schema) -> Result<(), Error> { match &self.command { Command::Openapi(_) => validate::validate_openapi(schema).map_err(Error::Schematools), Command::JsonSchema(_) => { @@ -108,16 +108,16 @@ impl Opts { } pub fn execute(opts: Opts, client: &Client) -> Result<(), Error> { - let mut schema = opts.get_schema(client)?; + let schema = opts.get_schema(client)?; match &opts.command { Command::Openapi(o) => { o.verbose.start()?; - opts.run(&mut schema) + opts.run(&schema) } Command::JsonSchema(o) => { o.verbose.start()?; - opts.run(&mut schema) + opts.run(&schema) } } } diff --git a/crates/schematools/src/codegen/jsonschema/oneof/extractor.rs b/crates/schematools/src/codegen/jsonschema/oneof/extractor.rs index d7b1a9e..82776ff 100644 --- a/crates/schematools/src/codegen/jsonschema/oneof/extractor.rs +++ b/crates/schematools/src/codegen/jsonschema/oneof/extractor.rs @@ -30,10 +30,17 @@ pub trait Extractor { #[derive(Serialize)] pub struct DiscriminatorMeta { pub property: String, - pub value: String, + pub value: DiscriminatorValue, pub properties: Option, } +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub enum DiscriminatorValue { + Model(String), + Simple(FlatModel), +} + pub struct Simple { properties: Vec, } @@ -115,8 +122,8 @@ impl Simple { value: f .model .as_ref() - .and_then(|m| m.name.clone()) - .unwrap_or(f.name.clone().unwrap()), + .and_then(|m| m.name.clone().map(DiscriminatorValue::Model)) + .unwrap_or(DiscriminatorValue::Simple(f.clone())), properties: Some(object.properties.len()), } }) @@ -131,7 +138,11 @@ impl Simple { DiscriminatorMeta { property: f.name.clone().unwrap(), - value: f.model.as_ref().and_then(|m| m.name.clone()).unwrap(), + value: f + .model + .as_ref() + .and_then(|m| m.name.clone().map(DiscriminatorValue::Model)) + .unwrap_or(DiscriminatorValue::Simple(f.clone())), properties: Some(object.properties.len() - 1), } }) @@ -213,7 +224,7 @@ impl Extractor for Discriminator { DISCRIMINATOR_META.to_owned(), serde_json::to_value(DiscriminatorMeta { property: self.property.clone(), - value: value.clone(), + value: DiscriminatorValue::Model(value.clone()), properties, }) .unwrap(), diff --git a/crates/schematools/src/codegen/jsonschema/oneof/mod.rs b/crates/schematools/src/codegen/jsonschema/oneof/mod.rs index 8988d4b..3922b69 100644 --- a/crates/schematools/src/codegen/jsonschema/oneof/mod.rs +++ b/crates/schematools/src/codegen/jsonschema/oneof/mod.rs @@ -176,7 +176,19 @@ mod tests { "_discriminator".to_string(), json!({ "property": "some", - "value": "some", + "value": { + "simple": { + "name": "some", + "type": "string", + "model": null, + "required": true, + "nullable": false, + "validation": null, + "x": {}, + "description": null, + "default": null + } + }, "properties": 1 }) )] @@ -202,7 +214,19 @@ mod tests { "_discriminator".to_string(), json!({ "property": "testing", - "value": "testing", + "value": { + "simple": { + "name": "testing", + "type": "number", + "model": null, + "required": true, + "nullable": false, + "validation": null, + "x": {}, + "description": null, + "default": null + } + }, "properties": 1 }) )] @@ -263,7 +287,7 @@ mod tests { "_discriminator".to_string(), json!({ "property": "type", - "value": "value1", + "value": {"model": "value1"}, "properties": 1 }) )] @@ -289,7 +313,7 @@ mod tests { "_discriminator".to_string(), json!({ "property": "type", - "value": "value2", + "value": {"model":"value2"}, "properties": 1 }) )] diff --git a/crates/schematools/src/codegen/jsonschema/required.rs b/crates/schematools/src/codegen/jsonschema/required.rs index d5e24fd..7488111 100644 --- a/crates/schematools/src/codegen/jsonschema/required.rs +++ b/crates/schematools/src/codegen/jsonschema/required.rs @@ -2,7 +2,7 @@ use crate::scope::SchemaScope; use serde_json::Map; use serde_json::Value; -pub fn extract_required(data: &Map, scope: &mut SchemaScope) -> Vec { +pub fn extract_required(data: &Map, scope: &SchemaScope) -> Vec { match data.get("required").unwrap_or(&serde_json::json!([])) { Value::Array(a) => a.iter().map(|v| v.as_str().unwrap().to_string()).collect(), _ => { diff --git a/crates/schematools/src/codegen/jsonschema/types.rs b/crates/schematools/src/codegen/jsonschema/types.rs index 4bf0e26..d195599 100644 --- a/crates/schematools/src/codegen/jsonschema/types.rs +++ b/crates/schematools/src/codegen/jsonschema/types.rs @@ -588,7 +588,7 @@ impl Default for Attributes { } impl AnyType { - pub fn model(schema: &Map, scope: &mut SchemaScope) -> Model { + pub fn model(schema: &Map, scope: &SchemaScope) -> Model { log::debug!("{}: {:?} may be invalid json schema", scope, schema); Model::new(ModelType::AnyType(Self {})) diff --git a/crates/schematools/src/codegen/openapi/endpoint.rs b/crates/schematools/src/codegen/openapi/endpoint.rs index 793a646..87ef6ad 100644 --- a/crates/schematools/src/codegen/openapi/endpoint.rs +++ b/crates/schematools/src/codegen/openapi/endpoint.rs @@ -40,7 +40,7 @@ pub fn extract_endpoints( path: &str, scope: &mut SchemaScope, mcontainer: &mut ModelContainer, - scontainer: &mut security::SecuritySchemes, + scontainer: &security::SecuritySchemes, resolver: &SchemaResolver, options: &JsonSchemaExtractOptions, ) -> Result, Error> { @@ -93,7 +93,7 @@ fn new_endpoint( method: &str, scope: &mut SchemaScope, mcontainer: &mut ModelContainer, - scontainer: &mut security::SecuritySchemes, + scontainer: &security::SecuritySchemes, resolver: &SchemaResolver, options: &JsonSchemaExtractOptions, ) -> Result { diff --git a/crates/schematools/src/codegen/openapi/mod.rs b/crates/schematools/src/codegen/openapi/mod.rs index 5c2c622..153b32b 100644 --- a/crates/schematools/src/codegen/openapi/mod.rs +++ b/crates/schematools/src/codegen/openapi/mod.rs @@ -154,7 +154,7 @@ pub fn extract( tools::each_node(root, &mut scope, "path:security", |node, _parts, scope| { scope.glue("security"); - let schemes = security::extract_defaults(node, scope, &mut scontainer)?; + let schemes = security::extract_defaults(node, scope, &scontainer)?; for scheme in schemes { scontainer.add_default(scheme); } @@ -247,7 +247,7 @@ pub fn extract( path, scope, &mut mcontainer, - &mut scontainer, + &scontainer, resolver, options, )?; diff --git a/crates/schematools/src/codegen/openapi/security.rs b/crates/schematools/src/codegen/openapi/security.rs index 70195af..d2b8b5c 100644 --- a/crates/schematools/src/codegen/openapi/security.rs +++ b/crates/schematools/src/codegen/openapi/security.rs @@ -87,7 +87,7 @@ pub fn new_scheme( pub fn extract_defaults( node: &Value, scope: &mut SchemaScope, - scontainer: &mut SecuritySchemes, + scontainer: &SecuritySchemes, ) -> Result, Error> { match node { Value::Array(scheme_names) => { @@ -113,7 +113,7 @@ pub fn extract_defaults( pub fn extract_default( node: &Value, - scontainer: &mut SecuritySchemes, + scontainer: &SecuritySchemes, ) -> Result, Error> { match node { Value::Object(data) => { diff --git a/crates/schematools/src/process/dereference.rs b/crates/schematools/src/process/dereference.rs index 88c7953..9a7d617 100644 --- a/crates/schematools/src/process/dereference.rs +++ b/crates/schematools/src/process/dereference.rs @@ -212,7 +212,7 @@ fn process_node( } } -fn process_discriminator(root: &mut Value, ctx: &mut DereferencerContext) { +fn process_discriminator(root: &mut Value, ctx: &DereferencerContext) { log::debug!("{}: processing discriminator", ctx.scope); if let Value::Object(ref mut map) = root {