Implement JsonSchema for Range/RangeInclusive
This commit is contained in:
parent
b334bef91a
commit
fe861ac3a1
10 changed files with 203 additions and 50 deletions
|
@ -2,6 +2,7 @@ use crate::gen::SchemaGenerator;
|
||||||
use crate::schema::*;
|
use crate::schema::*;
|
||||||
use crate::JsonSchema;
|
use crate::JsonSchema;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
use std::ops::{Range, RangeInclusive};
|
||||||
|
|
||||||
impl<T: JsonSchema> JsonSchema for Option<T> {
|
impl<T: JsonSchema> JsonSchema for Option<T> {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
@ -74,8 +75,6 @@ fn with_null_type(mut obj: SchemaObject) -> SchemaObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: JsonSchema, E: JsonSchema> JsonSchema for Result<T, E> {
|
impl<T: JsonSchema, E: JsonSchema> JsonSchema for Result<T, E> {
|
||||||
no_ref_schema!();
|
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
format!("Result_Of_{}_Or_{}", T::schema_name(), E::schema_name())
|
format!("Result_Of_{}_Or_{}", T::schema_name(), E::schema_name())
|
||||||
}
|
}
|
||||||
|
@ -83,18 +82,16 @@ impl<T: JsonSchema, E: JsonSchema> JsonSchema for Result<T, E> {
|
||||||
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
let mut ok_schema = SchemaObject::default();
|
let mut ok_schema = SchemaObject::default();
|
||||||
ok_schema.instance_type = Some(InstanceType::Object.into());
|
ok_schema.instance_type = Some(InstanceType::Object.into());
|
||||||
ok_schema.object().required.insert("Ok".to_owned());
|
let obj = ok_schema.object();
|
||||||
ok_schema
|
obj.required.insert("Ok".to_owned());
|
||||||
.object()
|
obj.properties
|
||||||
.properties
|
|
||||||
.insert("Ok".to_owned(), gen.subschema_for::<T>());
|
.insert("Ok".to_owned(), gen.subschema_for::<T>());
|
||||||
|
|
||||||
let mut err_schema = SchemaObject::default();
|
let mut err_schema = SchemaObject::default();
|
||||||
err_schema.instance_type = Some(InstanceType::Object.into());
|
err_schema.instance_type = Some(InstanceType::Object.into());
|
||||||
err_schema.object().required.insert("Err".to_owned());
|
let obj = err_schema.object();
|
||||||
err_schema
|
obj.required.insert("Err".to_owned());
|
||||||
.object()
|
obj.properties
|
||||||
.properties
|
|
||||||
.insert("Err".to_owned(), gen.subschema_for::<E>());
|
.insert("Err".to_owned(), gen.subschema_for::<E>());
|
||||||
|
|
||||||
let mut schema = SchemaObject::default();
|
let mut schema = SchemaObject::default();
|
||||||
|
@ -103,6 +100,35 @@ impl<T: JsonSchema, E: JsonSchema> JsonSchema for Result<T, E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: JsonSchema> JsonSchema for Range<T> {
|
||||||
|
fn schema_name() -> String {
|
||||||
|
format!("Range_Of_{}", T::schema_name())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
|
let mut schema = SchemaObject::default();
|
||||||
|
schema.instance_type = Some(InstanceType::Object.into());
|
||||||
|
let obj = schema.object();
|
||||||
|
obj.required.insert("start".to_owned());
|
||||||
|
obj.required.insert("end".to_owned());
|
||||||
|
obj.properties
|
||||||
|
.insert("start".to_owned(), gen.subschema_for::<T>());
|
||||||
|
obj.properties
|
||||||
|
.insert("end".to_owned(), gen.subschema_for::<T>());
|
||||||
|
schema.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: JsonSchema> JsonSchema for RangeInclusive<T> {
|
||||||
|
fn schema_name() -> String {
|
||||||
|
<Range<T>>::schema_name()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
|
<Range<T>>::json_schema(gen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> JsonSchema for std::marker::PhantomData<T> {
|
impl<T: ?Sized> JsonSchema for std::marker::PhantomData<T> {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,13 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
macro_rules! simple_impl {
|
macro_rules! simple_impl {
|
||||||
($type:tt => $instance_type:ident) => {
|
($type:ty => $instance_type:ident) => {
|
||||||
simple_impl!($type => $instance_type, None);
|
simple_impl!($type => $instance_type, None);
|
||||||
};
|
};
|
||||||
($type:tt => $instance_type:ident, $format: literal) => {
|
($type:ty => $instance_type:ident, $format: literal) => {
|
||||||
simple_impl!($type => $instance_type, Some($format.to_owned()));
|
simple_impl!($type => $instance_type, Some($format.to_owned()));
|
||||||
};
|
};
|
||||||
($type:tt => $instance_type:ident, $($format:tt)+) => {
|
($type:ty => $instance_type:ident, $($format:tt)+) => {
|
||||||
impl JsonSchema for $type {
|
impl JsonSchema for $type {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,11 @@ impl JsonSchema for Duration {
|
||||||
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
let mut schema = SchemaObject::default();
|
let mut schema = SchemaObject::default();
|
||||||
schema.instance_type = Some(InstanceType::Object.into());
|
schema.instance_type = Some(InstanceType::Object.into());
|
||||||
let properties = &mut schema.object().properties;
|
let obj = schema.object();
|
||||||
properties.insert("secs".to_owned(), <u64>::json_schema(gen));
|
obj.required.insert("secs".to_owned());
|
||||||
properties.insert("nanos".to_owned(), <u32>::json_schema(gen));
|
obj.required.insert("nanos".to_owned());
|
||||||
|
obj.properties.insert("secs".to_owned(), <u64>::json_schema(gen));
|
||||||
|
obj.properties.insert("nanos".to_owned(), <u32>::json_schema(gen));
|
||||||
schema.into()
|
schema.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,9 +28,11 @@ impl JsonSchema for SystemTime {
|
||||||
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
let mut schema = SchemaObject::default();
|
let mut schema = SchemaObject::default();
|
||||||
schema.instance_type = Some(InstanceType::Object.into());
|
schema.instance_type = Some(InstanceType::Object.into());
|
||||||
let properties = &mut schema.object().properties;
|
let obj = schema.object();
|
||||||
properties.insert("secs_since_epoch".to_owned(), <u64>::json_schema(gen));
|
obj.required.insert("secs_since_epoch".to_owned());
|
||||||
properties.insert("nanos_since_epoch".to_owned(), <u32>::json_schema(gen));
|
obj.required.insert("nanos_since_epoch".to_owned());
|
||||||
|
obj.properties.insert("secs_since_epoch".to_owned(), <u64>::json_schema(gen));
|
||||||
|
obj.properties.insert("nanos_since_epoch".to_owned(), <u32>::json_schema(gen));
|
||||||
schema.into()
|
schema.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! schema_for {
|
macro_rules! schema_for {
|
||||||
($type:path) => {
|
($type:ty) => {
|
||||||
$crate::gen::SchemaGenerator::default().into_root_schema_for::<$type>()
|
$crate::gen::SchemaGenerator::default().into_root_schema_for::<$type>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,14 +144,14 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! get_or_insert_default_fn {
|
macro_rules! get_or_insert_default_fn {
|
||||||
($name:ident, $ret:path) => {
|
($name:ident, $ret:ty) => {
|
||||||
get_or_insert_default_fn!(
|
get_or_insert_default_fn!(
|
||||||
concat!("Returns a mutable reference to this schema's [`", stringify!($ret), "`](#structfield.", stringify!($name), "), creating it if it was `None`."),
|
concat!("Returns a mutable reference to this schema's [`", stringify!($ret), "`](#structfield.", stringify!($name), "), creating it if it was `None`."),
|
||||||
$name,
|
$name,
|
||||||
$ret
|
$ret
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
($doc:expr, $name:ident, $ret:path) => {
|
($doc:expr, $name:ident, $ret:ty) => {
|
||||||
#[doc = $doc]
|
#[doc = $doc]
|
||||||
pub fn $name(&mut self) -> &mut $ret {
|
pub fn $name(&mut self) -> &mut $ret {
|
||||||
self.$name.get_or_insert_with(Default::default)
|
self.$name.get_or_insert_with(Default::default)
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Duration": {
|
"Duration": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"nanos",
|
||||||
|
"secs"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"nanos": {
|
"nanos": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
@ -30,6 +34,10 @@
|
||||||
},
|
},
|
||||||
"SystemTime": {
|
"SystemTime": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"nanos_since_epoch",
|
||||||
|
"secs_since_epoch"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"nanos_since_epoch": {
|
"nanos_since_epoch": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
|
53
schemars/tests/expected/range.json
Normal file
53
schemars/tests/expected/range.json
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "MyStruct",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"inclusive",
|
||||||
|
"range"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"inclusive": {
|
||||||
|
"$ref": "#/definitions/Range_Of_Number"
|
||||||
|
},
|
||||||
|
"range": {
|
||||||
|
"$ref": "#/definitions/Range_Of_Integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"Range_Of_Integer": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"end",
|
||||||
|
"start"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"end": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint"
|
||||||
|
},
|
||||||
|
"start": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Range_Of_Number": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"end",
|
||||||
|
"start"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"end": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"start": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,59 @@
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"title": "Result_Of_MyStruct_Or_Array_Of_String",
|
"title": "Container",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"result1",
|
||||||
|
"result2"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"result1": {
|
||||||
|
"$ref": "#/definitions/Result_Of_MyStruct_Or_Array_Of_String"
|
||||||
|
},
|
||||||
|
"result2": {
|
||||||
|
"$ref": "#/definitions/Result_Of_Boolean_Or_Null"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"MyStruct": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"foo"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"foo": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Result_Of_Boolean_Or_Null": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"Ok"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"Ok": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"Err"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"Err": {
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Result_Of_MyStruct_Or_Array_Of_String": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -27,19 +80,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"definitions": {
|
|
||||||
"MyStruct": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"foo"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
15
schemars/tests/range.rs
Normal file
15
schemars/tests/range.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
mod util;
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use util::*;
|
||||||
|
use std::ops::{Range, RangeInclusive};
|
||||||
|
|
||||||
|
#[derive(Debug, JsonSchema)]
|
||||||
|
struct MyStruct {
|
||||||
|
range: Range<usize>,
|
||||||
|
inclusive: RangeInclusive<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn result() -> TestResult {
|
||||||
|
test_default_generated_schema::<MyStruct>("range")
|
||||||
|
}
|
|
@ -7,7 +7,13 @@ struct MyStruct {
|
||||||
foo: i32,
|
foo: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, JsonSchema)]
|
||||||
|
struct Container {
|
||||||
|
result1: Result<MyStruct, Vec<String>>,
|
||||||
|
result2: Result<bool, ()>,
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn result() -> TestResult {
|
fn result() -> TestResult {
|
||||||
test_default_generated_schema::<Result<MyStruct, Vec<String>>>("result")
|
test_default_generated_schema::<Container>("result")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue