From c4d42ec11a54e445f84d2101e9afd97b98735f69 Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Mon, 13 May 2024 22:02:30 +0100 Subject: [PATCH] Refactor `flatten` and move it to `_private`, remove `TempFixupForTests`, regenerate test schemas --- schemars/src/_private.rs | 60 ++++++++++ schemars/src/flatten.rs | 71 ----------- schemars/src/lib.rs | 1 - schemars/tests/expected/bytes.json | 4 +- schemars/tests/expected/chrono-types.json | 4 +- schemars/tests/expected/crate_alias.json | 4 +- schemars/tests/expected/deprecated-enum.json | 4 +- .../tests/expected/deprecated-struct.json | 4 +- .../expected/duration_and_systemtime.json | 16 +-- .../expected/enum-adjacent-tagged-duf.json | 32 ++--- .../tests/expected/enum-adjacent-tagged.json | 32 ++--- .../tests/expected/enum-external-duf.json | 8 +- schemars/tests/expected/enum-external.json | 8 +- .../tests/expected/enum-internal-duf.json | 8 +- schemars/tests/expected/enum-internal.json | 8 +- .../tests/expected/enum-untagged-duf.json | 8 +- schemars/tests/expected/enum-untagged.json | 8 +- schemars/tests/expected/examples.json | 4 +- schemars/tests/expected/flatten.json | 2 +- .../tests/expected/inline-subschemas.json | 2 +- .../tests/expected/macro_built_struct.json | 6 +- schemars/tests/expected/nonzero_ints.json | 8 +- schemars/tests/expected/os_strings.json | 8 +- schemars/tests/expected/range.json | 16 +-- schemars/tests/expected/remote_derive.json | 4 +- .../tests/expected/remote_derive_generic.json | 6 +- .../tests/expected/schema-name-custom.json | 4 +- .../tests/expected/schema-name-default.json | 4 +- .../expected/schema-name-mixed-generics.json | 8 +- .../expected/schema_settings-2019_09.json | 4 +- .../expected/schema_settings-openapi3.json | 4 +- schemars/tests/expected/schema_settings.json | 4 +- .../schema_with-enum-adjacent-tagged.json | 16 +-- .../expected/schema_with-enum-internal.json | 4 +- .../tests/expected/schema_with-struct.json | 4 +- .../tests/expected/skip_struct_fields.json | 4 +- .../struct-normal-additional-properties.json | 4 +- schemars/tests/expected/struct-normal.json | 4 +- schemars/tests/expected/validate.json | 24 ++-- schemars/tests/expected/validate_inner.json | 10 +- schemars/tests/expected/validate_newtype.json | 4 +- .../expected/validate_schemars_attrs.json | 24 ++-- schemars/tests/expected/validate_tuple.json | 4 +- schemars/tests/util/mod.rs | 32 ----- schemars_derive/src/schema_exprs.rs | 112 +++++++++--------- 45 files changed, 280 insertions(+), 330 deletions(-) delete mode 100644 schemars/src/flatten.rs diff --git a/schemars/src/_private.rs b/schemars/src/_private.rs index 2510401..129d92e 100644 --- a/schemars/src/_private.rs +++ b/schemars/src/_private.rs @@ -3,6 +3,7 @@ use crate::JsonSchema; use crate::Schema; use serde::Serialize; use serde_json::json; +use serde_json::map::Entry; use serde_json::Map; use serde_json::Value; @@ -174,3 +175,62 @@ pub fn apply_inner_validation(schema: &mut Schema, f: fn(&mut Schema) -> ()) { f(inner_schema); } } + +pub fn flatten(schema: &mut Schema, other: Schema) { + if let Value::Object(obj2) = other.to_value() { + let obj1 = schema.ensure_object(); + + for (key, value2) in obj2 { + match obj1.entry(key) { + Entry::Vacant(vacant) => { + vacant.insert(value2); + } + Entry::Occupied(mut occupied) => { + match occupied.key().as_str() { + // This special "type" handling can probably be removed once the enum variant `with`/`schema_with` behaviour is fixed + "type" => match (occupied.get_mut(), value2) { + (Value::Array(a1), Value::Array(mut a2)) => { + a2.retain(|v2| !a1.contains(v2)); + a1.extend(a2); + } + (v1, Value::Array(mut a2)) => { + if !a2.contains(v1) { + a2.push(std::mem::take(v1)); + *occupied.get_mut() = Value::Array(a2); + } + } + (Value::Array(a1), v2) => { + if !a1.contains(&v2) { + a1.push(v2); + } + } + (v1, v2) => { + if v1 != &v2 { + *occupied.get_mut() = + Value::Array(vec![std::mem::take(v1), v2]); + } + } + }, + "required" => { + if let Value::Array(a1) = occupied.into_mut() { + if let Value::Array(a2) = value2 { + a1.extend(a2); + } + } + } + "properties" | "patternProperties" => { + if let Value::Object(o1) = occupied.into_mut() { + if let Value::Object(o2) = value2 { + o1.extend(o2); + } + } + } + _ => { + // leave the original value as it is (don't modify `schema`) + } + }; + } + } + } + } +} diff --git a/schemars/src/flatten.rs b/schemars/src/flatten.rs deleted file mode 100644 index 69b0361..0000000 --- a/schemars/src/flatten.rs +++ /dev/null @@ -1,71 +0,0 @@ -use serde_json::map::Entry; -use serde_json::Value; - -use crate::Schema; - -impl Schema { - /// This function is only public for use by schemars_derive. - /// - /// It should not be considered part of the public API. - #[doc(hidden)] - pub fn flatten(mut self, other: Self) -> Schema { - if let Value::Object(obj2) = other.to_value() { - let obj1 = self.ensure_object(); - - for (key, value2) in obj2 { - match obj1.entry(key) { - Entry::Vacant(vacant) => { - vacant.insert(value2); - } - Entry::Occupied(mut occupied) => { - match occupied.key().as_str() { - // This special "type" handling can probably be removed once the enum variant `with`/`schema_with` behaviour is fixed - "type" => match (occupied.get_mut(), value2) { - (Value::Array(a1), Value::Array(mut a2)) => { - a2.retain(|v2| !a1.contains(v2)); - a1.extend(a2); - } - (v1, Value::Array(mut a2)) => { - if !a2.contains(v1) { - a2.push(std::mem::take(v1)); - *occupied.get_mut() = Value::Array(a2); - } - } - (Value::Array(a1), v2) => { - if !a1.contains(&v2) { - a1.push(v2); - } - } - (v1, v2) => { - if v1 != &v2 { - *occupied.get_mut() = - Value::Array(vec![std::mem::take(v1), v2]); - } - } - }, - "required" => { - if let Value::Array(a1) = occupied.into_mut() { - if let Value::Array(a2) = value2 { - a1.extend(a2); - } - } - } - "properties" | "patternProperties" => { - if let Value::Object(o1) = occupied.into_mut() { - if let Value::Object(o2) = value2 { - o1.extend(o2); - } - } - } - _ => { - // leave the original value as it is (don't modify `self`) - } - }; - } - } - } - } - - self - } -} diff --git a/schemars/src/lib.rs b/schemars/src/lib.rs index fbe5f1d..32bb8c0 100644 --- a/schemars/src/lib.rs +++ b/schemars/src/lib.rs @@ -1,7 +1,6 @@ #![deny(unsafe_code)] #![doc = include_str!("../README.md")] -mod flatten; mod json_schema_impls; mod schema; mod ser; diff --git a/schemars/tests/expected/bytes.json b/schemars/tests/expected/bytes.json index 5e1f9a5..06458c6 100644 --- a/schemars/tests/expected/bytes.json +++ b/schemars/tests/expected/bytes.json @@ -8,7 +8,7 @@ "items": { "type": "integer", "format": "uint8", - "minimum": 0.0 + "minimum": 0 } }, { @@ -16,7 +16,7 @@ "items": { "type": "integer", "format": "uint8", - "minimum": 0.0 + "minimum": 0 } } ], diff --git a/schemars/tests/expected/chrono-types.json b/schemars/tests/expected/chrono-types.json index b96b00c..b9e333d 100644 --- a/schemars/tests/expected/chrono-types.json +++ b/schemars/tests/expected/chrono-types.json @@ -33,10 +33,10 @@ } }, "required": [ + "weekday", "date_time", "naive_date", "naive_date_time", - "naive_time", - "weekday" + "naive_time" ] } \ No newline at end of file diff --git a/schemars/tests/expected/crate_alias.json b/schemars/tests/expected/crate_alias.json index d37d482..b01fc0d 100644 --- a/schemars/tests/expected/crate_alias.json +++ b/schemars/tests/expected/crate_alias.json @@ -13,7 +13,7 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] } \ No newline at end of file diff --git a/schemars/tests/expected/deprecated-enum.json b/schemars/tests/expected/deprecated-enum.json index dab90ec..ee3de61 100644 --- a/schemars/tests/expected/deprecated-enum.json +++ b/schemars/tests/expected/deprecated-enum.json @@ -30,8 +30,8 @@ } }, "required": [ - "deprecated_field", - "foo" + "foo", + "deprecated_field" ] } }, diff --git a/schemars/tests/expected/deprecated-struct.json b/schemars/tests/expected/deprecated-struct.json index b915eb1..d2af941 100644 --- a/schemars/tests/expected/deprecated-struct.json +++ b/schemars/tests/expected/deprecated-struct.json @@ -14,7 +14,7 @@ }, "deprecated": true, "required": [ - "deprecated_field", - "foo" + "foo", + "deprecated_field" ] } \ No newline at end of file diff --git a/schemars/tests/expected/duration_and_systemtime.json b/schemars/tests/expected/duration_and_systemtime.json index b212599..71c17b7 100644 --- a/schemars/tests/expected/duration_and_systemtime.json +++ b/schemars/tests/expected/duration_and_systemtime.json @@ -21,17 +21,17 @@ "nanos": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "secs": { "type": "integer", "format": "uint64", - "minimum": 0.0 + "minimum": 0 } }, "required": [ - "nanos", - "secs" + "secs", + "nanos" ] }, "SystemTime": { @@ -40,17 +40,17 @@ "nanos_since_epoch": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "secs_since_epoch": { "type": "integer", "format": "uint64", - "minimum": 0.0 + "minimum": 0 } }, "required": [ - "nanos_since_epoch", - "secs_since_epoch" + "secs_since_epoch", + "nanos_since_epoch" ] } } diff --git a/schemars/tests/expected/enum-adjacent-tagged-duf.json b/schemars/tests/expected/enum-adjacent-tagged-duf.json index a89ab50..f746216 100644 --- a/schemars/tests/expected/enum-adjacent-tagged-duf.json +++ b/schemars/tests/expected/enum-adjacent-tagged-duf.json @@ -35,8 +35,8 @@ }, "additionalProperties": false, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -54,8 +54,8 @@ }, "additionalProperties": false, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -73,8 +73,8 @@ }, "additionalProperties": false, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -93,8 +93,8 @@ }, "additionalProperties": false, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, "t": { @@ -106,8 +106,8 @@ }, "additionalProperties": false, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -136,8 +136,8 @@ }, "additionalProperties": false, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -171,8 +171,8 @@ }, "additionalProperties": false, "required": [ - "c", - "t" + "t", + "c" ] } ], @@ -189,8 +189,8 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, "UnitStruct": { diff --git a/schemars/tests/expected/enum-adjacent-tagged.json b/schemars/tests/expected/enum-adjacent-tagged.json index 9380c5b..b977be0 100644 --- a/schemars/tests/expected/enum-adjacent-tagged.json +++ b/schemars/tests/expected/enum-adjacent-tagged.json @@ -33,8 +33,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -51,8 +51,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -69,8 +69,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -88,8 +88,8 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, "t": { @@ -100,8 +100,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -129,8 +129,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -162,8 +162,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] } ], @@ -180,8 +180,8 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, "UnitStruct": { diff --git a/schemars/tests/expected/enum-external-duf.json b/schemars/tests/expected/enum-external-duf.json index d492808..0351fa2 100644 --- a/schemars/tests/expected/enum-external-duf.json +++ b/schemars/tests/expected/enum-external-duf.json @@ -64,8 +64,8 @@ }, "additionalProperties": false, "required": [ - "bar", - "foo" + "foo", + "bar" ] } }, @@ -124,8 +124,8 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, "UnitStruct": { diff --git a/schemars/tests/expected/enum-external.json b/schemars/tests/expected/enum-external.json index b09f107..4c1d5a6 100644 --- a/schemars/tests/expected/enum-external.json +++ b/schemars/tests/expected/enum-external.json @@ -63,8 +63,8 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] } }, @@ -123,8 +123,8 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, "UnitStruct": { diff --git a/schemars/tests/expected/enum-internal-duf.json b/schemars/tests/expected/enum-internal-duf.json index 758bf9b..9c2aa9c 100644 --- a/schemars/tests/expected/enum-internal-duf.json +++ b/schemars/tests/expected/enum-internal-duf.json @@ -59,9 +59,9 @@ } }, "required": [ - "bar", + "typeProperty", "foo", - "typeProperty" + "bar" ] }, { @@ -81,9 +81,9 @@ }, "additionalProperties": false, "required": [ - "bar", + "typeProperty", "foo", - "typeProperty" + "bar" ] }, { diff --git a/schemars/tests/expected/enum-internal.json b/schemars/tests/expected/enum-internal.json index 765248f..7fd931c 100644 --- a/schemars/tests/expected/enum-internal.json +++ b/schemars/tests/expected/enum-internal.json @@ -57,9 +57,9 @@ } }, "required": [ - "bar", + "typeProperty", "foo", - "typeProperty" + "bar" ] }, { @@ -78,9 +78,9 @@ } }, "required": [ - "bar", + "typeProperty", "foo", - "typeProperty" + "bar" ] }, { diff --git a/schemars/tests/expected/enum-untagged-duf.json b/schemars/tests/expected/enum-untagged-duf.json index 7ce7d3d..e3f7c66 100644 --- a/schemars/tests/expected/enum-untagged-duf.json +++ b/schemars/tests/expected/enum-untagged-duf.json @@ -30,8 +30,8 @@ }, "additionalProperties": false, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, { @@ -66,8 +66,8 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, "UnitStruct": { diff --git a/schemars/tests/expected/enum-untagged.json b/schemars/tests/expected/enum-untagged.json index add81e4..2b23ffb 100644 --- a/schemars/tests/expected/enum-untagged.json +++ b/schemars/tests/expected/enum-untagged.json @@ -29,8 +29,8 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, { @@ -65,8 +65,8 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] }, "UnitStruct": { diff --git a/schemars/tests/expected/examples.json b/schemars/tests/expected/examples.json index 9c5c5ab..3203c4a 100644 --- a/schemars/tests/expected/examples.json +++ b/schemars/tests/expected/examples.json @@ -33,7 +33,7 @@ null ], "required": [ - "bar", - "foo" + "foo", + "bar" ] } \ No newline at end of file diff --git a/schemars/tests/expected/flatten.json b/schemars/tests/expected/flatten.json index ec0aff3..8f77dd2 100644 --- a/schemars/tests/expected/flatten.json +++ b/schemars/tests/expected/flatten.json @@ -26,8 +26,8 @@ } }, "required": [ - "b", "f", + "b", "s", "v" ] diff --git a/schemars/tests/expected/inline-subschemas.json b/schemars/tests/expected/inline-subschemas.json index fe4e83e..7ba76d5 100644 --- a/schemars/tests/expected/inline-subschemas.json +++ b/schemars/tests/expected/inline-subschemas.json @@ -9,7 +9,7 @@ "replicas": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 } }, "required": [ diff --git a/schemars/tests/expected/macro_built_struct.json b/schemars/tests/expected/macro_built_struct.json index 0c5840c..e958c8e 100644 --- a/schemars/tests/expected/macro_built_struct.json +++ b/schemars/tests/expected/macro_built_struct.json @@ -10,11 +10,11 @@ "x": { "type": "integer", "format": "uint8", - "minimum": 0.0 + "minimum": 0 } }, "required": [ - "v", - "x" + "x", + "v" ] } \ No newline at end of file diff --git a/schemars/tests/expected/nonzero_ints.json b/schemars/tests/expected/nonzero_ints.json index 3b83929..6ee5105 100644 --- a/schemars/tests/expected/nonzero_ints.json +++ b/schemars/tests/expected/nonzero_ints.json @@ -13,7 +13,7 @@ "nonzero_unsigned": { "type": "integer", "format": "uint32", - "minimum": 1.0 + "minimum": 1 }, "signed": { "type": "integer", @@ -22,13 +22,13 @@ "unsigned": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 } }, "required": [ - "nonzero_signed", + "unsigned", "nonzero_unsigned", "signed", - "unsigned" + "nonzero_signed" ] } \ No newline at end of file diff --git a/schemars/tests/expected/os_strings.json b/schemars/tests/expected/os_strings.json index 50448ed..927f3f9 100644 --- a/schemars/tests/expected/os_strings.json +++ b/schemars/tests/expected/os_strings.json @@ -11,8 +11,8 @@ } }, "required": [ - "borrowed", - "owned" + "owned", + "borrowed" ], "definitions": { "OsString": { @@ -25,7 +25,7 @@ "items": { "type": "integer", "format": "uint8", - "minimum": 0.0 + "minimum": 0 } } }, @@ -41,7 +41,7 @@ "items": { "type": "integer", "format": "uint16", - "minimum": 0.0 + "minimum": 0 } } }, diff --git a/schemars/tests/expected/range.json b/schemars/tests/expected/range.json index bb68e3a..19e4780 100644 --- a/schemars/tests/expected/range.json +++ b/schemars/tests/expected/range.json @@ -14,9 +14,9 @@ } }, "required": [ - "bound", + "range", "inclusive", - "range" + "bound" ], "definitions": { "Bound_of_string": { @@ -62,8 +62,8 @@ } }, "required": [ - "end", - "start" + "start", + "end" ] }, "Range_of_uint": { @@ -72,17 +72,17 @@ "end": { "type": "integer", "format": "uint", - "minimum": 0.0 + "minimum": 0 }, "start": { "type": "integer", "format": "uint", - "minimum": 0.0 + "minimum": 0 } }, "required": [ - "end", - "start" + "start", + "end" ] } } diff --git a/schemars/tests/expected/remote_derive.json b/schemars/tests/expected/remote_derive.json index 76df9b6..9477e0f 100644 --- a/schemars/tests/expected/remote_derive.json +++ b/schemars/tests/expected/remote_derive.json @@ -47,8 +47,8 @@ } }, "required": [ - "nanos", - "secs" + "secs", + "nanos" ] } } diff --git a/schemars/tests/expected/remote_derive_generic.json b/schemars/tests/expected/remote_derive_generic.json index d06320f..b533320 100644 --- a/schemars/tests/expected/remote_derive_generic.json +++ b/schemars/tests/expected/remote_derive_generic.json @@ -25,9 +25,9 @@ }, "required": [ "byte_or_bool2", - "fake_map", + "unit_or_t2", "s", - "unit_or_t2" + "fake_map" ], "definitions": { "Or_for_null_and_int32": { @@ -46,7 +46,7 @@ { "type": "integer", "format": "uint8", - "minimum": 0.0 + "minimum": 0 }, { "type": "boolean" diff --git a/schemars/tests/expected/schema-name-custom.json b/schemars/tests/expected/schema-name-custom.json index 4e6cc36..dc5336b 100644 --- a/schemars/tests/expected/schema-name-custom.json +++ b/schemars/tests/expected/schema-name-custom.json @@ -24,11 +24,11 @@ } }, "required": [ - "inner", "t", "u", "v", - "w" + "w", + "inner" ], "definitions": { "another-new-name": { diff --git a/schemars/tests/expected/schema-name-default.json b/schemars/tests/expected/schema-name-default.json index 39c39a9..7524c63 100644 --- a/schemars/tests/expected/schema-name-default.json +++ b/schemars/tests/expected/schema-name-default.json @@ -24,11 +24,11 @@ } }, "required": [ - "inner", "t", "u", "v", - "w" + "w", + "inner" ], "definitions": { "MySimpleStruct": { diff --git a/schemars/tests/expected/schema-name-mixed-generics.json b/schemars/tests/expected/schema-name-mixed-generics.json index 0da8044..fdadbab 100644 --- a/schemars/tests/expected/schema-name-mixed-generics.json +++ b/schemars/tests/expected/schema-name-mixed-generics.json @@ -12,8 +12,8 @@ } }, "required": [ - "foo", - "generic" + "generic", + "foo" ], "definitions": { "MySimpleStruct": { @@ -52,11 +52,11 @@ } }, "required": [ - "inner", "t", "u", "v", - "w" + "w", + "inner" ] } } diff --git a/schemars/tests/expected/schema_settings-2019_09.json b/schemars/tests/expected/schema_settings-2019_09.json index e51f397..947aa2e 100644 --- a/schemars/tests/expected/schema_settings-2019_09.json +++ b/schemars/tests/expected/schema_settings-2019_09.json @@ -29,8 +29,8 @@ }, "required": [ "int", - "value", - "values" + "values", + "value" ], "definitions": { "Inner": { diff --git a/schemars/tests/expected/schema_settings-openapi3.json b/schemars/tests/expected/schema_settings-openapi3.json index 5318b01..b6de302 100644 --- a/schemars/tests/expected/schema_settings-openapi3.json +++ b/schemars/tests/expected/schema_settings-openapi3.json @@ -24,8 +24,8 @@ }, "required": [ "int", - "value", - "values" + "values", + "value" ], "definitions": { "Inner": { diff --git a/schemars/tests/expected/schema_settings.json b/schemars/tests/expected/schema_settings.json index 07cdb0e..6a66ca0 100644 --- a/schemars/tests/expected/schema_settings.json +++ b/schemars/tests/expected/schema_settings.json @@ -29,8 +29,8 @@ }, "required": [ "int", - "value", - "values" + "values", + "value" ], "definitions": { "Inner": { diff --git a/schemars/tests/expected/schema_with-enum-adjacent-tagged.json b/schemars/tests/expected/schema_with-enum-adjacent-tagged.json index c29c59e..5b95671 100644 --- a/schemars/tests/expected/schema_with-enum-adjacent-tagged.json +++ b/schemars/tests/expected/schema_with-enum-adjacent-tagged.json @@ -24,8 +24,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -42,8 +42,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -71,8 +71,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] }, { @@ -89,8 +89,8 @@ } }, "required": [ - "c", - "t" + "t", + "c" ] } ] diff --git a/schemars/tests/expected/schema_with-enum-internal.json b/schemars/tests/expected/schema_with-enum-internal.json index 45bc8e9..90871ad 100644 --- a/schemars/tests/expected/schema_with-enum-internal.json +++ b/schemars/tests/expected/schema_with-enum-internal.json @@ -14,8 +14,8 @@ } }, "required": [ - "foo", - "typeProperty" + "typeProperty", + "foo" ] }, { diff --git a/schemars/tests/expected/schema_with-struct.json b/schemars/tests/expected/schema_with-struct.json index 40b5c56..7cc55bf 100644 --- a/schemars/tests/expected/schema_with-struct.json +++ b/schemars/tests/expected/schema_with-struct.json @@ -15,8 +15,8 @@ } }, "required": [ + "foo", "bar", - "baz", - "foo" + "baz" ] } \ No newline at end of file diff --git a/schemars/tests/expected/skip_struct_fields.json b/schemars/tests/expected/skip_struct_fields.json index 21e01a6..7890298 100644 --- a/schemars/tests/expected/skip_struct_fields.json +++ b/schemars/tests/expected/skip_struct_fields.json @@ -18,7 +18,7 @@ } }, "required": [ - "included", - "writable" + "writable", + "included" ] } \ No newline at end of file diff --git a/schemars/tests/expected/struct-normal-additional-properties.json b/schemars/tests/expected/struct-normal-additional-properties.json index ed8602a..5ff105c 100644 --- a/schemars/tests/expected/struct-normal-additional-properties.json +++ b/schemars/tests/expected/struct-normal-additional-properties.json @@ -19,7 +19,7 @@ }, "additionalProperties": false, "required": [ - "bar", - "foo" + "foo", + "bar" ] } \ No newline at end of file diff --git a/schemars/tests/expected/struct-normal.json b/schemars/tests/expected/struct-normal.json index e6fe68b..0a5a0af 100644 --- a/schemars/tests/expected/struct-normal.json +++ b/schemars/tests/expected/struct-normal.json @@ -18,7 +18,7 @@ } }, "required": [ - "bar", - "foo" + "foo", + "bar" ] } \ No newline at end of file diff --git a/schemars/tests/expected/validate.json b/schemars/tests/expected/validate.json index 38aabcc..2d6e43c 100644 --- a/schemars/tests/expected/validate.json +++ b/schemars/tests/expected/validate.json @@ -31,14 +31,14 @@ "min_max": { "type": "number", "format": "float", - "maximum": 100.0, + "maximum": 100, "minimum": 0.01 }, "min_max2": { "type": "number", "format": "float", - "maximum": 1000.0, - "minimum": 1.0 + "maximum": 1000, + "minimum": 1 }, "non_empty_str": { "type": "string", @@ -84,21 +84,21 @@ } }, "required": [ - "contains_str1", - "contains_str2", - "email_address", - "homepage", - "map_contains", "min_max", "min_max2", - "non_empty_str", - "non_empty_str2", - "pair", "regex_str1", "regex_str2", "regex_str3", - "required_option", + "contains_str1", + "contains_str2", + "email_address", "tel", + "homepage", + "non_empty_str", + "non_empty_str2", + "pair", + "map_contains", + "required_option", "x" ] } \ No newline at end of file diff --git a/schemars/tests/expected/validate_inner.json b/schemars/tests/expected/validate_inner.json index ffe6792..f8a7eca 100644 --- a/schemars/tests/expected/validate_inner.json +++ b/schemars/tests/expected/validate_inner.json @@ -25,8 +25,8 @@ "items": { "type": "integer", "format": "int32", - "maximum": 10.0, - "minimum": -10.0 + "maximum": 10, + "minimum": -10 } }, "vec_str_length": { @@ -65,10 +65,10 @@ "required": [ "array_str_length", "slice_str_contains", - "vec_i32_range", + "vec_str_regex", "vec_str_length", "vec_str_length2", - "vec_str_regex", - "vec_str_url" + "vec_str_url", + "vec_i32_range" ] } \ No newline at end of file diff --git a/schemars/tests/expected/validate_newtype.json b/schemars/tests/expected/validate_newtype.json index 796aecd..4c1146e 100644 --- a/schemars/tests/expected/validate_newtype.json +++ b/schemars/tests/expected/validate_newtype.json @@ -3,6 +3,6 @@ "title": "NewType", "type": "integer", "format": "uint8", - "maximum": 10.0, - "minimum": 0.0 + "maximum": 10, + "minimum": 0 } \ No newline at end of file diff --git a/schemars/tests/expected/validate_schemars_attrs.json b/schemars/tests/expected/validate_schemars_attrs.json index 438b4aa..fa2dbcd 100644 --- a/schemars/tests/expected/validate_schemars_attrs.json +++ b/schemars/tests/expected/validate_schemars_attrs.json @@ -31,14 +31,14 @@ "min_max": { "type": "number", "format": "float", - "maximum": 100.0, + "maximum": 100, "minimum": 0.01 }, "min_max2": { "type": "number", "format": "float", - "maximum": 1000.0, - "minimum": 1.0 + "maximum": 1000, + "minimum": 1 }, "non_empty_str": { "type": "string", @@ -84,21 +84,21 @@ } }, "required": [ - "contains_str1", - "contains_str2", - "email_address", - "homepage", - "map_contains", "min_max", "min_max2", - "non_empty_str", - "non_empty_str2", - "pair", "regex_str1", "regex_str2", "regex_str3", - "required_option", + "contains_str1", + "contains_str2", + "email_address", "tel", + "homepage", + "non_empty_str", + "non_empty_str2", + "pair", + "map_contains", + "required_option", "x" ] } \ No newline at end of file diff --git a/schemars/tests/expected/validate_tuple.json b/schemars/tests/expected/validate_tuple.json index 8ab6eaa..619b8c4 100644 --- a/schemars/tests/expected/validate_tuple.json +++ b/schemars/tests/expected/validate_tuple.json @@ -6,8 +6,8 @@ { "type": "integer", "format": "uint8", - "maximum": 10.0, - "minimum": 0.0 + "maximum": 10, + "minimum": 0 }, { "type": "boolean" diff --git a/schemars/tests/util/mod.rs b/schemars/tests/util/mod.rs index 99cf677..3376c02 100644 --- a/schemars/tests/util/mod.rs +++ b/schemars/tests/util/mod.rs @@ -1,5 +1,4 @@ use pretty_assertions::assert_eq; -use schemars::visit::Visitor; use schemars::{gen::SchemaSettings, schema_for, JsonSchema, Schema}; use std::error::Error; use std::fs; @@ -19,15 +18,6 @@ pub fn test_default_generated_schema(file: &str) -> TestResult { } pub fn test_schema(actual: &Schema, file: &str) -> TestResult { - // TEMP for easier comparison of schemas handling changes that don't actually affect a schema: - // - `required` ordering has changed - // - previously `f64` properties may now be integers - let actual = &{ - let mut actual = actual.clone(); - TempFixupForTests.visit_schema(&mut actual); - actual - }; - let expected_json = match fs::read_to_string(format!("tests/expected/{}.json", file)) { Ok(j) => j, Err(e) => { @@ -50,25 +40,3 @@ fn write_actual_to_file(schema: &Schema, file: &str) -> TestResult { fs::write(format!("tests/actual/{}.json", file), actual_json)?; Ok(()) } - -struct TempFixupForTests; - -impl schemars::visit::Visitor for TempFixupForTests { - fn visit_schema(&mut self, schema: &mut Schema) { - schemars::visit::visit_schema(self, schema); - - if let Some(object) = schema.as_object_mut() { - if let Some(serde_json::Value::Array(required)) = object.get_mut("required") { - required.sort_unstable_by(|a, b| a.as_str().cmp(&b.as_str())); - } - - for (key, value) in object { - if key == "multipleOf" || key.ends_with("aximum") || key.ends_with("inimum") { - if let Some(f) = value.as_f64() { - *value = f.into(); - } - } - } - } - } -} diff --git a/schemars_derive/src/schema_exprs.rs b/schemars_derive/src/schema_exprs.rs index 7a1de81..6357172 100644 --- a/schemars_derive/src/schema_exprs.rs +++ b/schemars_derive/src/schema_exprs.rs @@ -434,73 +434,68 @@ fn expr_for_struct( default: &SerdeDefault, deny_unknown_fields: bool, ) -> TokenStream { - let (flattened_fields, property_fields): (Vec<_>, Vec<_>) = fields - .iter() - .filter(|f| !f.serde_attrs.skip_deserializing() || !f.serde_attrs.skip_serializing()) - .partition(|f| f.serde_attrs.flatten()); - let set_container_default = match default { SerdeDefault::None => None, SerdeDefault::Default => Some(quote!(let container_default = Self::default();)), SerdeDefault::Path(path) => Some(quote!(let container_default = #path();)), }; - let properties: Vec<_> = property_fields - .into_iter() + let properties: Vec<_> = fields + .iter() + .filter(|f| !f.serde_attrs.skip_deserializing() || !f.serde_attrs.skip_serializing()) .map(|field| { - let name = field.name(); - let default = field_default_expr(field, set_container_default.is_some()); + if field.serde_attrs.flatten() { + let (ty, type_def) = type_for_field_schema(field); - let (ty, type_def) = type_for_field_schema(field); + let required = field.validation_attrs.required(); - let has_default = default.is_some(); - let required = field.validation_attrs.required(); + let args = quote!(gen, #required); + let mut schema_expr = quote_spanned! {ty.span()=> + schemars::_private::json_schema_for_flatten::<#ty>(#args) + }; - let metadata = SchemaMetadata { - read_only: field.serde_attrs.skip_deserializing(), - write_only: field.serde_attrs.skip_serializing(), - default, - ..field.attrs.as_metadata() - }; + prepend_type_def(type_def, &mut schema_expr); - let gen = quote!(gen); - let mut schema_expr = if field.validation_attrs.required() { - quote_spanned! {ty.span()=> - <#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(#gen) + quote! { + schemars::_private::flatten(&mut schema, #schema_expr); } } else { - quote_spanned! {ty.span()=> - #gen.subschema_for::<#ty>() - } - }; + let name = field.name(); + let default = field_default_expr(field, set_container_default.is_some()); - metadata.apply_to_schema(&mut schema_expr); - field.validation_attrs.apply_to_schema(&mut schema_expr); + let (ty, type_def) = type_for_field_schema(field); - quote! { - { - #type_def - schemars::_private::insert_object_property::<#ty>(&mut schema, #name, #has_default, #required, #schema_expr); - } - } - }) - .collect(); + let has_default = default.is_some(); + let required = field.validation_attrs.required(); - let flattens: Vec<_> = flattened_fields - .into_iter() - .map(|field| { - let (ty, type_def) = type_for_field_schema(field); + let metadata = SchemaMetadata { + read_only: field.serde_attrs.skip_deserializing(), + write_only: field.serde_attrs.skip_serializing(), + default, + ..field.attrs.as_metadata() + }; - let required = field.validation_attrs.required(); + let gen = quote!(gen); + let mut schema_expr = if field.validation_attrs.required() { + quote_spanned! {ty.span()=> + <#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(#gen) + } + } else { + quote_spanned! {ty.span()=> + #gen.subschema_for::<#ty>() + } + }; - let args = quote!(gen, #required); - let mut schema_expr = quote_spanned! {ty.span()=> - schemars::_private::json_schema_for_flatten::<#ty>(#args) - }; + metadata.apply_to_schema(&mut schema_expr); + field.validation_attrs.apply_to_schema(&mut schema_expr); - prepend_type_def(type_def, &mut schema_expr); - schema_expr - }) + quote! { + { + #type_def + schemars::_private::insert_object_property::<#ty>(&mut schema, #name, #has_default, #required, #schema_expr); + } + }} + }) .collect(); let set_additional_properties = if deny_unknown_fields { @@ -510,17 +505,16 @@ fn expr_for_struct( } else { TokenStream::new() }; - quote! { - { - #set_container_default - let mut schema = schemars::json_schema!({ - "type": "object", - #set_additional_properties - }); - #(#properties)* - schema #(.flatten(#flattens))* - } - } + + quote! ({ + #set_container_default + let mut schema = schemars::json_schema!({ + "type": "object", + #set_additional_properties + }); + #(#properties)* + schema + }) } fn field_default_expr(field: &Field, container_has_default: bool) -> Option {