Skip to content

Commit 7e257e0

Browse files
committed
Update tests to account for schema name case changes, and fix flattening to make it consistent with previous (possibly buggy?) behaviour
1 parent 65fb44b commit 7e257e0

13 files changed

+108
-49
lines changed

schemars/src/_private.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ pub fn new_internally_tagged_enum(
8989
}
9090
},
9191
"required": [tag_name],
92-
"additionalProperties": false,
9392
});
9493

9594
if deny_unknown_fields {

schemars/src/flatten.rs

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use serde_json::map::Entry;
12
use serde_json::Value;
23

34
use crate::schema::*;
@@ -8,16 +9,64 @@ impl Schema {
89
/// It should not be considered part of the public API.
910
#[doc(hidden)]
1011
pub fn flatten(mut self, other: Self) -> Schema {
11-
if let Value::Object(obj2) = other.into() {
12+
// This special null-type-schema handling is here for backward-compatibility, but needs reviewing.
13+
// I think it's only needed to make internally-tagged enum unit variants behave correctly, but that
14+
// should be handled entirely within schemars_derive.
15+
if other
16+
.as_object()
17+
.and_then(|o| o.get("type"))
18+
.and_then(|t| t.as_str())
19+
== Some("null")
20+
{
21+
return self;
22+
}
23+
24+
if let Value::Object(mut obj2) = other.to_value() {
1225
let obj1 = self.ensure_object();
1326

27+
let ap2 = obj2.remove("additionalProperties");
28+
if let Entry::Occupied(mut ap1) = obj1.entry("additionalProperties") {
29+
match ap2 {
30+
Some(ap2) => {
31+
flatten_additional_properties(ap1.get_mut(), ap2);
32+
}
33+
None => {
34+
ap1.remove();
35+
}
36+
}
37+
}
38+
1439
for (key, value2) in obj2 {
1540
match obj1.entry(key) {
16-
serde_json::map::Entry::Vacant(vacant) => {
41+
Entry::Vacant(vacant) => {
1742
vacant.insert(value2);
1843
}
19-
serde_json::map::Entry::Occupied(mut occupied) => {
44+
Entry::Occupied(mut occupied) => {
2045
match occupied.key().as_str() {
46+
// This special "type" handling can probably be removed once the enum variant `with`/`schema_with` behaviour is fixed
47+
"type" => match (occupied.get_mut(), value2) {
48+
(Value::Array(a1), Value::Array(mut a2)) => {
49+
a2.retain(|v2| !a1.contains(v2));
50+
a1.extend(a2);
51+
}
52+
(v1, Value::Array(mut a2)) => {
53+
if !a2.contains(v1) {
54+
a2.push(std::mem::take(v1));
55+
*occupied.get_mut() = Value::Array(a2);
56+
}
57+
}
58+
(Value::Array(a1), v2) => {
59+
if !a1.contains(&v2) {
60+
a1.push(v2);
61+
}
62+
}
63+
(v1, v2) => {
64+
if v1 != &v2 {
65+
*occupied.get_mut() =
66+
Value::Array(vec![std::mem::take(v1), v2]);
67+
}
68+
}
69+
},
2170
"required" => {
2271
if let Value::Array(a1) = occupied.into_mut() {
2372
if let Value::Array(a2) = value2 {
@@ -32,10 +81,6 @@ impl Schema {
3281
}
3382
}
3483
}
35-
"additionalProperties" => {
36-
let value1 = std::mem::take(occupied.get_mut());
37-
occupied.insert(flatten_additional_properties(value1, value2));
38-
}
3984
_ => {
4085
// leave the original value as it is (don't modify `self`)
4186
}
@@ -49,14 +94,18 @@ impl Schema {
4994
}
5095
}
5196

52-
fn flatten_additional_properties(v1: Value, v2: Value) -> Value {
97+
// TODO validate behaviour when flattening a normal struct into a struct with deny_unknown_fields
98+
fn flatten_additional_properties(v1: &mut Value, v2: Value) {
5399
match (v1, v2) {
54-
(Value::Bool(true), _) | (_, Value::Bool(true)) => Value::Bool(true),
55-
(Value::Bool(false), v) | (v, Value::Bool(false)) => v,
56-
(Value::Object(mut o1), Value::Object(o2)) => {
100+
(v1, Value::Bool(true)) => {
101+
*v1 = Value::Bool(true);
102+
}
103+
(v1 @ Value::Bool(false), v2) => {
104+
*v1 = v2;
105+
}
106+
(Value::Object(o1), Value::Object(o2)) => {
57107
o1.extend(o2);
58-
Value::Object(o1)
59108
}
60-
(v, _) => v,
109+
_ => {}
61110
}
62111
}

schemars/tests/enum.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum External {
3131
},
3232
UnitTwo,
3333
Tuple(i32, bool),
34+
// FIXME this should probably only replace the "payload" of the enum
3435
#[schemars(with = "i32")]
3536
WithInt,
3637
}
@@ -53,6 +54,7 @@ enum Internal {
5354
bar: bool,
5455
},
5556
UnitTwo,
57+
// FIXME this should probably only replace the "payload" of the enum
5658
#[schemars(with = "i32")]
5759
WithInt,
5860
}
@@ -75,6 +77,7 @@ enum Untagged {
7577
bar: bool,
7678
},
7779
Tuple(i32, bool),
80+
// FIXME this should probably only replace the "payload" of the enum
7881
#[schemars(with = "i32")]
7982
WithInt,
8083
}
@@ -98,6 +101,7 @@ enum Adjacent {
98101
},
99102
Tuple(i32, bool),
100103
UnitTwo,
104+
// FIXME this should probably only replace the "payload" of the enum
101105
#[schemars(with = "i32")]
102106
WithInt,
103107
}

schemars/tests/enum_deny_unknown_fields.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum External {
3333
},
3434
UnitTwo,
3535
Tuple(i32, bool),
36+
// FIXME this should probably only replace the "payload" of the enum
3637
#[schemars(with = "i32")]
3738
WithInt,
3839
}
@@ -56,6 +57,7 @@ enum Internal {
5657
bar: bool,
5758
},
5859
UnitTwo,
60+
// FIXME this should only replace the "payload" of the enum (which doesn't even make sense for unit enums!)
5961
#[schemars(with = "i32")]
6062
WithInt,
6163
}
@@ -79,6 +81,7 @@ enum Untagged {
7981
bar: bool,
8082
},
8183
Tuple(i32, bool),
84+
// FIXME this should probably only replace the "payload" of the enum
8285
#[schemars(with = "i32")]
8386
WithInt,
8487
}
@@ -103,6 +106,7 @@ enum Adjacent {
103106
},
104107
Tuple(i32, bool),
105108
UnitTwo,
109+
// FIXME this should probably only replace the "payload" of the enum
106110
#[schemars(with = "i32")]
107111
WithInt,
108112
}

schemars/tests/expected/enum-internal-duf.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,7 @@
127127
"WithInt"
128128
]
129129
}
130-
},
131-
"additionalProperties": false
130+
}
132131
}
133132
]
134133
}

schemars/tests/expected/range.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"$ref": "#/definitions/Range_of_double"
1616
},
1717
"bound": {
18-
"$ref": "#/definitions/Bound_of_String"
18+
"$ref": "#/definitions/Bound_of_string"
1919
}
2020
},
2121
"definitions": {
@@ -55,7 +55,7 @@
5555
}
5656
}
5757
},
58-
"Bound_of_String": {
58+
"Bound_of_string": {
5959
"oneOf": [
6060
{
6161
"type": "object",

schemars/tests/expected/remote_derive_generic.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
],
1111
"properties": {
1212
"byte_or_bool2": {
13-
"$ref": "#/definitions/Or_for_uint8_and_Boolean"
13+
"$ref": "#/definitions/Or_for_uint8_and_boolean"
1414
},
1515
"unit_or_t2": {
16-
"$ref": "#/definitions/Or_for_Null_and_int32"
16+
"$ref": "#/definitions/Or_for_null_and_int32"
1717
},
1818
"s": {
1919
"$ref": "#/definitions/Str"
@@ -30,7 +30,7 @@
3030
}
3131
},
3232
"definitions": {
33-
"Or_for_uint8_and_Boolean": {
33+
"Or_for_uint8_and_boolean": {
3434
"anyOf": [
3535
{
3636
"type": "integer",
@@ -42,7 +42,7 @@
4242
}
4343
]
4444
},
45-
"Or_for_Null_and_int32": {
45+
"Or_for_null_and_int32": {
4646
"anyOf": [
4747
{
4848
"type": "null"

schemars/tests/expected/result.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
],
99
"properties": {
1010
"result1": {
11-
"$ref": "#/definitions/Result_of_MyStruct_or_Array_of_String"
11+
"$ref": "#/definitions/Result_of_MyStruct_or_Array_of_string"
1212
},
1313
"result2": {
14-
"$ref": "#/definitions/Result_of_Boolean_or_Null"
14+
"$ref": "#/definitions/Result_of_boolean_or_null"
1515
}
1616
},
1717
"definitions": {
18-
"Result_of_MyStruct_or_Array_of_String": {
18+
"Result_of_MyStruct_or_Array_of_string": {
1919
"oneOf": [
2020
{
2121
"type": "object",
@@ -56,7 +56,7 @@
5656
}
5757
}
5858
},
59-
"Result_of_Boolean_or_Null": {
59+
"Result_of_boolean_or_null": {
6060
"oneOf": [
6161
{
6262
"type": "object",

schemars/tests/expected/schema-name-custom.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "http://json-schema.org/draft-07/schema#",
3-
"title": "a-new-name-Array_of_String-int32-int32",
3+
"title": "a-new-name-Array_of_string-int32-int32",
44
"type": "object",
55
"required": [
66
"inner",
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
{
22
"$schema": "http://json-schema.org/draft-07/schema#",
3-
"title": "MyStruct_for_int32_and_Null_and_Boolean_and_Array_of_String",
3+
"title": "MyStruct_for_int32_and_null_and_boolean_and_Array_of_string",
44
"type": "object",
5-
"required": [
6-
"inner",
7-
"t",
8-
"u",
9-
"v",
10-
"w"
11-
],
125
"properties": {
6+
"inner": {
7+
"$ref": "#/definitions/MySimpleStruct"
8+
},
139
"t": {
1410
"type": "integer",
1511
"format": "int32"
@@ -25,23 +21,27 @@
2521
"items": {
2622
"type": "string"
2723
}
28-
},
29-
"inner": {
30-
"$ref": "#/definitions/MySimpleStruct"
3124
}
3225
},
26+
"required": [
27+
"inner",
28+
"t",
29+
"u",
30+
"v",
31+
"w"
32+
],
3333
"definitions": {
3434
"MySimpleStruct": {
3535
"type": "object",
36-
"required": [
37-
"foo"
38-
],
3936
"properties": {
4037
"foo": {
4138
"type": "integer",
4239
"format": "int32"
4340
}
44-
}
41+
},
42+
"required": [
43+
"foo"
44+
]
4545
}
4646
}
4747
}

schemars/tests/expected/schema-name-mixed-generics.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "http://json-schema.org/draft-07/schema#",
3-
"title": "MixedGenericStruct_for_MyStruct_for_int32_and_Null_and_Boolean_and_Array_of_String_and_42_and_z",
3+
"title": "MixedGenericStruct_for_MyStruct_for_int32_and_null_and_boolean_and_Array_of_string_and_42_and_z",
44
"type": "object",
55
"required": [
66
"foo",
@@ -12,7 +12,7 @@
1212
"format": "int32"
1313
},
1414
"generic": {
15-
"$ref": "#/definitions/MyStruct_for_int32_and_Null_and_Boolean_and_Array_of_String"
15+
"$ref": "#/definitions/MyStruct_for_int32_and_null_and_boolean_and_Array_of_string"
1616
}
1717
},
1818
"definitions": {
@@ -28,7 +28,7 @@
2828
}
2929
}
3030
},
31-
"MyStruct_for_int32_and_Null_and_Boolean_and_Array_of_String": {
31+
"MyStruct_for_int32_and_null_and_boolean_and_Array_of_string": {
3232
"type": "object",
3333
"required": [
3434
"inner",

schemars/tests/expected/schema_with-enum-internal.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
},
2323
{
2424
"type": [
25-
"boolean",
26-
"object"
25+
"object",
26+
"boolean"
2727
],
2828
"required": [
2929
"typeProperty"
@@ -39,8 +39,8 @@
3939
},
4040
{
4141
"type": [
42-
"boolean",
43-
"object"
42+
"object",
43+
"boolean"
4444
],
4545
"required": [
4646
"typeProperty"

0 commit comments

Comments
 (0)