Refactor flatten
and move it to _private
, remove TempFixupForTests
, regenerate test schemas
This commit is contained in:
parent
18300c67bb
commit
c4d42ec11a
45 changed files with 280 additions and 330 deletions
|
@ -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`)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
#![deny(unsafe_code)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
mod flatten;
|
||||
mod json_schema_impls;
|
||||
mod schema;
|
||||
mod ser;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -33,10 +33,10 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"weekday",
|
||||
"date_time",
|
||||
"naive_date",
|
||||
"naive_date_time",
|
||||
"naive_time",
|
||||
"weekday"
|
||||
"naive_time"
|
||||
]
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
|
@ -30,8 +30,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"deprecated_field",
|
||||
"foo"
|
||||
"foo",
|
||||
"deprecated_field"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
},
|
||||
"deprecated": true,
|
||||
"required": [
|
||||
"deprecated_field",
|
||||
"foo"
|
||||
"foo",
|
||||
"deprecated_field"
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -124,8 +124,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"UnitStruct": {
|
||||
|
|
|
@ -63,8 +63,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -123,8 +123,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"UnitStruct": {
|
||||
|
|
|
@ -59,9 +59,9 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"typeProperty",
|
||||
"foo",
|
||||
"typeProperty"
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -81,9 +81,9 @@
|
|||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"bar",
|
||||
"typeProperty",
|
||||
"foo",
|
||||
"typeProperty"
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -57,9 +57,9 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"typeProperty",
|
||||
"foo",
|
||||
"typeProperty"
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -78,9 +78,9 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"typeProperty",
|
||||
"foo",
|
||||
"typeProperty"
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -66,8 +66,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"UnitStruct": {
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -65,8 +65,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"UnitStruct": {
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
null
|
||||
],
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
|
@ -26,8 +26,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"b",
|
||||
"f",
|
||||
"b",
|
||||
"s",
|
||||
"v"
|
||||
]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"replicas": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
"x": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"v",
|
||||
"x"
|
||||
"x",
|
||||
"v"
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"nanos",
|
||||
"secs"
|
||||
"secs",
|
||||
"nanos"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"inner",
|
||||
"t",
|
||||
"u",
|
||||
"v",
|
||||
"w"
|
||||
"w",
|
||||
"inner"
|
||||
],
|
||||
"definitions": {
|
||||
"another-new-name": {
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"inner",
|
||||
"t",
|
||||
"u",
|
||||
"v",
|
||||
"w"
|
||||
"w",
|
||||
"inner"
|
||||
],
|
||||
"definitions": {
|
||||
"MySimpleStruct": {
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"foo",
|
||||
"generic"
|
||||
"generic",
|
||||
"foo"
|
||||
],
|
||||
"definitions": {
|
||||
"MySimpleStruct": {
|
||||
|
@ -52,11 +52,11 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"inner",
|
||||
"t",
|
||||
"u",
|
||||
"v",
|
||||
"w"
|
||||
"w",
|
||||
"inner"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
},
|
||||
"required": [
|
||||
"int",
|
||||
"value",
|
||||
"values"
|
||||
"values",
|
||||
"value"
|
||||
],
|
||||
"definitions": {
|
||||
"Inner": {
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
},
|
||||
"required": [
|
||||
"int",
|
||||
"value",
|
||||
"values"
|
||||
"values",
|
||||
"value"
|
||||
],
|
||||
"definitions": {
|
||||
"Inner": {
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
},
|
||||
"required": [
|
||||
"int",
|
||||
"value",
|
||||
"values"
|
||||
"values",
|
||||
"value"
|
||||
],
|
||||
"definitions": {
|
||||
"Inner": {
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"foo",
|
||||
"typeProperty"
|
||||
"typeProperty",
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
"foo"
|
||||
"baz"
|
||||
]
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"included",
|
||||
"writable"
|
||||
"writable",
|
||||
"included"
|
||||
]
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"bar",
|
||||
"foo"
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -3,6 +3,6 @@
|
|||
"title": "NewType",
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"maximum": 10.0,
|
||||
"minimum": 0.0
|
||||
"maximum": 10,
|
||||
"minimum": 0
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -6,8 +6,8 @@
|
|||
{
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"maximum": 10.0,
|
||||
"minimum": 0.0
|
||||
"maximum": 10,
|
||||
"minimum": 0
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
|
|
|
@ -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<T: JsonSchema>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<TokenStream> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue