Add strongly-typed validation fields
This commit is contained in:
parent
5de6bcfdef
commit
88a8e0a706
9 changed files with 597 additions and 99 deletions
|
@ -1,7 +1,6 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Map, Result};
|
||||
use serde_json::json;
|
||||
use crate::{JsonSchema, Result};
|
||||
|
||||
// Does not require T: JsonSchema.
|
||||
impl<T> JsonSchema for [T; 0] {
|
||||
|
@ -12,11 +11,12 @@ impl<T> JsonSchema for [T; 0] {
|
|||
}
|
||||
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("maxItems".to_owned(), json!(0));
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
extensions,
|
||||
array: ArrayValidation {
|
||||
max_items: Some(0),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
.into())
|
||||
|
@ -34,13 +34,14 @@ macro_rules! array_impls {
|
|||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("minItems".to_owned(), json!($len));
|
||||
extensions.insert("maxItems".to_owned(), json!($len));
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
array: ArrayValidation {
|
||||
items: Some(gen.subschema_for::<T>()?.into()),
|
||||
extensions,
|
||||
max_items: Some($len),
|
||||
min_items: Some($len),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
|
@ -69,9 +70,12 @@ mod tests {
|
|||
schema.instance_type,
|
||||
Some(SingleOrVec::from(InstanceType::Array))
|
||||
);
|
||||
assert_eq!(schema.extensions.get("minItems"), Some(&json!(8)));
|
||||
assert_eq!(schema.extensions.get("maxItems"), Some(&json!(8)));
|
||||
assert_eq!(schema.items, Some(SingleOrVec::from(schema_for::<i32>())));
|
||||
assert_eq!(
|
||||
schema.array.items,
|
||||
Some(SingleOrVec::from(schema_for::<i32>()))
|
||||
);
|
||||
assert_eq!(schema.array.max_items, Some(8));
|
||||
assert_eq!(schema.array.min_items, Some(8));
|
||||
}
|
||||
|
||||
// SomeStruct does not implement JsonSchema
|
||||
|
@ -84,6 +88,6 @@ mod tests {
|
|||
schema.instance_type,
|
||||
Some(SingleOrVec::from(InstanceType::Array))
|
||||
);
|
||||
assert_eq!(schema.extensions.get("maxItems"), Some(&json!(0)));
|
||||
assert_eq!(schema.array.max_items, Some(0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::gen::{BoolSchemas, SchemaGenerator};
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Map, Result};
|
||||
use serde_json::json;
|
||||
use crate::{JsonSchema, Result};
|
||||
|
||||
macro_rules! map_impl {
|
||||
($($desc:tt)+) => {
|
||||
|
@ -20,18 +19,18 @@ macro_rules! map_impl {
|
|||
let subschema = gen.subschema_for::<V>()?;
|
||||
let json_schema_bool = gen.settings().bool_schemas == BoolSchemas::AdditionalPropertiesOnly
|
||||
&& subschema == gen.schema_for_any();
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert(
|
||||
"additionalProperties".to_owned(),
|
||||
let additional_properties =
|
||||
if json_schema_bool {
|
||||
json!(true)
|
||||
true.into()
|
||||
} else {
|
||||
json!(subschema)
|
||||
}
|
||||
);
|
||||
subschema.into()
|
||||
};
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Object.into()),
|
||||
extensions,
|
||||
object: ObjectValidation {
|
||||
additional_properties: Some(Box::new(additional_properties)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
|
@ -62,10 +61,10 @@ mod tests {
|
|||
schema.instance_type,
|
||||
Some(SingleOrVec::from(InstanceType::Object))
|
||||
);
|
||||
assert_eq!(
|
||||
schema.extensions.get("additionalProperties"),
|
||||
Some(&json!(true))
|
||||
);
|
||||
let additional_properties = schema.object
|
||||
.additional_properties
|
||||
.expect("additionalProperties field present");
|
||||
assert_eq!(*additional_properties, Schema::Bool(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,10 +79,10 @@ mod tests {
|
|||
schema.instance_type,
|
||||
Some(SingleOrVec::from(InstanceType::Object))
|
||||
);
|
||||
assert_eq!(
|
||||
schema.extensions.get("additionalProperties"),
|
||||
Some(&json!(Schema::Object(Default::default())))
|
||||
);
|
||||
let additional_properties = schema.object
|
||||
.additional_properties
|
||||
.expect("additionalProperties field present");
|
||||
assert_eq!(*additional_properties, Schema::Object(Default::default()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -102,10 +101,10 @@ mod tests {
|
|||
schema.instance_type,
|
||||
Some(SingleOrVec::from(InstanceType::Object))
|
||||
);
|
||||
assert_eq!(
|
||||
schema.extensions.get("additionalProperties"),
|
||||
Some(&json!(schema_for::<i32>()))
|
||||
);
|
||||
let additional_properties = schema.object
|
||||
.additional_properties
|
||||
.expect("additionalProperties field present");
|
||||
assert_eq!(*additional_properties, schema_for::<i32>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Map, Result};
|
||||
use serde_json::json;
|
||||
use crate::{JsonSchema, Result};
|
||||
|
||||
macro_rules! simple_impl {
|
||||
($type:tt => $instance_type:ident) => {
|
||||
|
@ -57,12 +56,13 @@ impl JsonSchema for char {
|
|||
}
|
||||
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("minLength".to_owned(), json!(1));
|
||||
extensions.insert("maxLength".to_owned(), json!(1));
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::String.into()),
|
||||
extensions,
|
||||
string: StringValidation {
|
||||
min_length: Some(1),
|
||||
max_length: Some(1),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
.into())
|
||||
|
|
|
@ -17,8 +17,11 @@ macro_rules! seq_impl {
|
|||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
array: ArrayValidation {
|
||||
items: Some(gen.subschema_for::<T>()?.into()),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Map, Result};
|
||||
use serde_json::json;
|
||||
use crate::{JsonSchema, Result};
|
||||
|
||||
macro_rules! tuple_impls {
|
||||
($($len:expr => ($($name:ident)+))+) => {
|
||||
|
@ -14,16 +13,17 @@ macro_rules! tuple_impls {
|
|||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("minItems".to_owned(), json!($len));
|
||||
extensions.insert("maxItems".to_owned(), json!($len));
|
||||
let items = vec![
|
||||
$(gen.subschema_for::<$name>()?),+
|
||||
];
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
array: ArrayValidation {
|
||||
items: Some(items.into()),
|
||||
extensions,
|
||||
max_items: Some($len),
|
||||
min_items: Some($len),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
|
@ -64,14 +64,14 @@ mod tests {
|
|||
schema.instance_type,
|
||||
Some(SingleOrVec::from(InstanceType::Array))
|
||||
);
|
||||
assert_eq!(schema.extensions.get("minItems"), Some(&json!(2)));
|
||||
assert_eq!(schema.extensions.get("maxItems"), Some(&json!(2)));
|
||||
assert_eq!(
|
||||
schema.items,
|
||||
schema.array.items,
|
||||
Some(SingleOrVec::Vec(vec![
|
||||
schema_for::<i32>(),
|
||||
schema_for::<bool>()
|
||||
]))
|
||||
);
|
||||
assert_eq!(schema.array.max_items, Some(2));
|
||||
assert_eq!(schema.array.min_items, Some(2));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,9 +43,6 @@ impl Schema {
|
|||
id: s1.id.or(s2.id),
|
||||
title: s1.title.or(s2.title),
|
||||
description: s1.description.or(s2.description),
|
||||
items: s1.items.or(s2.items),
|
||||
properties: extend(s1.properties, s2.properties),
|
||||
required: extend(s1.required, s2.required),
|
||||
definitions: extend(s1.definitions, s2.definitions),
|
||||
extensions: extend(s1.extensions, s2.extensions),
|
||||
// TODO do the following make sense?
|
||||
|
@ -56,6 +53,38 @@ impl Schema {
|
|||
any_of: s1.any_of.or(s2.any_of),
|
||||
one_of: s1.one_of.or(s2.one_of),
|
||||
not: s1.not.or(s2.not),
|
||||
if_schema: s1.if_schema.or(s2.if_schema),
|
||||
then_schema: s1.then_schema.or(s2.then_schema),
|
||||
else_schema: s1.else_schema.or(s2.else_schema),
|
||||
number: NumberValidation {
|
||||
multiple_of: s1.number.multiple_of.or(s2.number.multiple_of),
|
||||
maximum: s1.number.maximum.or(s2.number.maximum),
|
||||
exclusive_maximum: s1.number.exclusive_maximum.or(s2.number.exclusive_maximum),
|
||||
minimum: s1.number.minimum.or(s2.number.minimum),
|
||||
exclusive_minimum: s1.number.exclusive_minimum.or(s2.number.exclusive_minimum),
|
||||
},
|
||||
string: StringValidation {
|
||||
max_length: s1.string.max_length.or(s2.string.max_length),
|
||||
min_length: s1.string.min_length.or(s2.string.min_length),
|
||||
pattern: s1.string.pattern.or(s2.string.pattern),
|
||||
},
|
||||
array: ArrayValidation {
|
||||
items: s1.array.items.or(s2.array.items),
|
||||
additional_items: s1.array.additional_items.or(s2.array.additional_items),
|
||||
max_items: s1.array.max_items.or(s2.array.max_items),
|
||||
min_items: s1.array.min_items.or(s2.array.min_items),
|
||||
unique_items: s1.array.unique_items.or(s2.array.unique_items),
|
||||
contains: s1.array.contains.or(s2.array.contains),
|
||||
},
|
||||
object: ObjectValidation {
|
||||
max_properties: s1.object.max_properties.or(s2.object.max_properties),
|
||||
min_properties: s1.object.min_properties.or(s2.object.min_properties),
|
||||
required: extend(s1.object.required, s2.object.required),
|
||||
properties: extend(s1.object.properties, s2.object.properties),
|
||||
pattern_properties: extend(s1.object.pattern_properties, s2.object.pattern_properties),
|
||||
additional_properties: s1.object.additional_properties.or(s2.object.additional_properties),
|
||||
property_names: s1.object.property_names.or(s2.object.property_names),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -111,12 +140,6 @@ pub struct SchemaObject {
|
|||
#[serde(rename = "enum", skip_serializing_if = "Option::is_none")]
|
||||
pub enum_values: Option<Vec<Value>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub items: Option<SingleOrVec<Schema>>,
|
||||
#[serde(skip_serializing_if = "Map::is_empty")]
|
||||
pub properties: Map<String, Schema>,
|
||||
#[serde(skip_serializing_if = "Set::is_empty")]
|
||||
pub required: Set<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub all_of: Option<Vec<Schema>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub any_of: Option<Vec<Schema>>,
|
||||
|
@ -124,12 +147,88 @@ pub struct SchemaObject {
|
|||
pub one_of: Option<Vec<Schema>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub not: Option<Box<Schema>>,
|
||||
#[serde(rename = "if", skip_serializing_if = "Option::is_none")]
|
||||
pub if_schema: Option<Box<Schema>>,
|
||||
#[serde(rename = "then", skip_serializing_if = "Option::is_none")]
|
||||
pub then_schema: Option<Box<Schema>>,
|
||||
#[serde(rename = "else", skip_serializing_if = "Option::is_none")]
|
||||
pub else_schema: Option<Box<Schema>>,
|
||||
#[serde(skip_serializing_if = "Map::is_empty")]
|
||||
pub definitions: Map<String, Schema>,
|
||||
#[serde(flatten)]
|
||||
pub number: NumberValidation,
|
||||
#[serde(flatten)]
|
||||
pub string: StringValidation,
|
||||
#[serde(flatten)]
|
||||
pub array: ArrayValidation,
|
||||
#[serde(flatten)]
|
||||
pub object: ObjectValidation,
|
||||
#[serde(flatten)]
|
||||
pub extensions: Map<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase", default)]
|
||||
pub struct NumberValidation {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub multiple_of: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub maximum: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub exclusive_maximum: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub minimum: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub exclusive_minimum: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase", default)]
|
||||
pub struct StringValidation {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub max_length: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub min_length: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub pattern: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase", default)]
|
||||
pub struct ArrayValidation {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub items: Option<SingleOrVec<Schema>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub additional_items: Option<Box<Schema>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub max_items: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub min_items: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub unique_items: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub contains: Option<Box<Schema>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase", default)]
|
||||
pub struct ObjectValidation {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub max_properties: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub min_properties: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Set::is_empty")]
|
||||
pub required: Set<String>,
|
||||
#[serde(skip_serializing_if = "Map::is_empty")]
|
||||
pub properties: Map<String, Schema>,
|
||||
#[serde(skip_serializing_if = "Map::is_empty")]
|
||||
pub pattern_properties: Map<String, Schema>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub additional_properties: Option<Box<Schema>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub property_names: Option<Box<Schema>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum InstanceType {
|
||||
|
|
|
@ -26,14 +26,14 @@
|
|||
},
|
||||
"Ref": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"$ref"
|
||||
],
|
||||
"properties": {
|
||||
"$ref": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"$ref"
|
||||
]
|
||||
}
|
||||
},
|
||||
"Schema": {
|
||||
"anyOf": [
|
||||
|
@ -59,6 +59,34 @@
|
|||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"additionalItems": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Ref"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SchemaObject"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"additionalProperties": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Ref"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SchemaObject"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"allOf": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
@ -73,6 +101,20 @@
|
|||
},
|
||||
"nullable": true
|
||||
},
|
||||
"contains": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Ref"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SchemaObject"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"definitions": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
|
@ -83,15 +125,53 @@
|
|||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"else": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Ref"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SchemaObject"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"enum": {
|
||||
"type": "array",
|
||||
"items": {},
|
||||
"nullable": true
|
||||
},
|
||||
"exclusiveMaximum": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"nullable": true
|
||||
},
|
||||
"exclusiveMinimum": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"nullable": true
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"if": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Ref"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SchemaObject"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
@ -106,6 +186,51 @@
|
|||
],
|
||||
"nullable": true
|
||||
},
|
||||
"maxItems": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"nullable": true
|
||||
},
|
||||
"maxLength": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"nullable": true
|
||||
},
|
||||
"maxProperties": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"nullable": true
|
||||
},
|
||||
"maximum": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"nullable": true
|
||||
},
|
||||
"minItems": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"nullable": true
|
||||
},
|
||||
"minLength": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"nullable": true
|
||||
},
|
||||
"minProperties": {
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"nullable": true
|
||||
},
|
||||
"minimum": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"nullable": true
|
||||
},
|
||||
"multipleOf": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"nullable": true
|
||||
},
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
@ -127,18 +252,56 @@
|
|||
},
|
||||
"nullable": true
|
||||
},
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"patternProperties": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/components/schemas/Schema"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/components/schemas/Schema"
|
||||
}
|
||||
},
|
||||
"propertyNames": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Ref"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SchemaObject"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"required": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Ref"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SchemaObject"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
|
@ -156,6 +319,10 @@
|
|||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"uniqueItems": {
|
||||
"type": "boolean",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
|
|
|
@ -26,14 +26,14 @@
|
|||
},
|
||||
"Ref": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"$ref"
|
||||
],
|
||||
"properties": {
|
||||
"$ref": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"$ref"
|
||||
]
|
||||
}
|
||||
},
|
||||
"Schema": {
|
||||
"anyOf": [
|
||||
|
@ -71,6 +71,26 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"additionalItems": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Schema"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"additionalProperties": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Schema"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"allOf": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
@ -97,6 +117,16 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"contains": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Schema"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"definitions": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
|
@ -113,6 +143,16 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"else": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Schema"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"enum": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
@ -124,6 +164,28 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"exclusiveMaximum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"exclusiveMinimum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"format": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
@ -134,6 +196,16 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"if": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Schema"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
@ -144,6 +216,105 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"maxItems": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "uint32"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "uint32"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxProperties": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "uint32"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"maximum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minItems": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "uint32"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minLength": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "uint32"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minProperties": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "uint32"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minimum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"multipleOf": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
@ -167,18 +338,54 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"pattern": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"patternProperties": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/Schema"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/Schema"
|
||||
}
|
||||
},
|
||||
"propertyNames": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Schema"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Schema"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
@ -198,6 +405,16 @@
|
|||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
|
|
|
@ -142,6 +142,7 @@ fn schema_for_external_tagged_enum<'a>(
|
|||
let sub_schema = schema_for_untagged_enum_variant(variant, cattrs);
|
||||
wrap_schema_fields(quote! {
|
||||
instance_type: Some(schemars::schema::InstanceType::Object.into()),
|
||||
object: schemars::schema::ObjectValidation {
|
||||
properties: {
|
||||
let mut props = schemars::Map::new();
|
||||
props.insert(#name.to_owned(), #sub_schema);
|
||||
|
@ -152,6 +153,8 @@ fn schema_for_external_tagged_enum<'a>(
|
|||
required.insert(#name.to_owned());
|
||||
required
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
})
|
||||
}));
|
||||
|
||||
|
@ -173,6 +176,7 @@ fn schema_for_internal_tagged_enum<'a>(
|
|||
});
|
||||
let schema = wrap_schema_fields(quote! {
|
||||
instance_type: Some(schemars::schema::InstanceType::Object.into()),
|
||||
object: schemars::schema::ObjectValidation {
|
||||
properties: {
|
||||
let mut props = schemars::Map::new();
|
||||
props.insert(#tag_name.to_owned(), #type_schema);
|
||||
|
@ -183,6 +187,8 @@ fn schema_for_internal_tagged_enum<'a>(
|
|||
required.insert(#tag_name.to_owned());
|
||||
required
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
if is_unit_variant(&variant) {
|
||||
schema
|
||||
|
@ -262,6 +268,7 @@ fn schema_for_struct(fields: &[Field], cattrs: &attr::Container) -> TokenStream
|
|||
|
||||
let schema = wrap_schema_fields(quote! {
|
||||
instance_type: Some(schemars::schema::InstanceType::Object.into()),
|
||||
object: schemars::schema::ObjectValidation {
|
||||
properties: {
|
||||
let mut props = schemars::Map::new();
|
||||
#(#recurse)*
|
||||
|
@ -272,6 +279,8 @@ fn schema_for_struct(fields: &[Field], cattrs: &attr::Container) -> TokenStream
|
|||
#(required.insert(#required.to_owned());)*
|
||||
required
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
|
||||
let flattens = flat.iter().map(|field| {
|
||||
|
@ -300,10 +309,10 @@ fn get_json_schema_type(field: &Field) -> Box<dyn ToTokens> {
|
|||
let se_with_segments = without_last_element(field.attrs.serialize_with(), "serialize");
|
||||
if de_with_segments == se_with_segments {
|
||||
if let Some(expr_path) = de_with_segments {
|
||||
return Box::from(expr_path);
|
||||
return Box::new(expr_path);
|
||||
}
|
||||
}
|
||||
Box::from(field.ty.clone())
|
||||
Box::new(field.ty.clone())
|
||||
}
|
||||
|
||||
fn without_last_element(path: Option<&syn::ExprPath>, last: &str) -> Option<syn::ExprPath> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue