Generate schema from any serializable value (#75)
Implement schema_for_value!(...) macro
This commit is contained in:
parent
0957204bc1
commit
f6482fd460
19 changed files with 1179 additions and 5 deletions
80
schemars/tests/expected/from_value_2019_09.json
Normal file
80
schemars/tests/expected/from_value_2019_09.json
Normal file
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2019-09/schema",
|
||||
"title": "MyStruct",
|
||||
"examples": [
|
||||
{
|
||||
"myBool": true,
|
||||
"myInnerStruct": {
|
||||
"my_empty_map": {},
|
||||
"my_empty_vec": [],
|
||||
"my_map": {
|
||||
"": 0.0
|
||||
},
|
||||
"my_tuple": [
|
||||
"💩",
|
||||
42
|
||||
],
|
||||
"my_vec": [
|
||||
"hello",
|
||||
"world"
|
||||
]
|
||||
},
|
||||
"myInt": 123,
|
||||
"myNullableEnum": null
|
||||
}
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"myInt": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"myBool": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"myNullableEnum": true,
|
||||
"myInnerStruct": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"my_map": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"my_vec": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"my_empty_map": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"my_empty_vec": {
|
||||
"type": "array",
|
||||
"items": true
|
||||
},
|
||||
"my_tuple": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "string",
|
||||
"maxLength": 1,
|
||||
"minLength": 1
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
}
|
||||
],
|
||||
"maxItems": 2,
|
||||
"minItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
80
schemars/tests/expected/from_value_draft07.json
Normal file
80
schemars/tests/expected/from_value_draft07.json
Normal file
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "MyStruct",
|
||||
"examples": [
|
||||
{
|
||||
"myBool": true,
|
||||
"myInnerStruct": {
|
||||
"my_empty_map": {},
|
||||
"my_empty_vec": [],
|
||||
"my_map": {
|
||||
"": 0.0
|
||||
},
|
||||
"my_tuple": [
|
||||
"💩",
|
||||
42
|
||||
],
|
||||
"my_vec": [
|
||||
"hello",
|
||||
"world"
|
||||
]
|
||||
},
|
||||
"myInt": 123,
|
||||
"myNullableEnum": null
|
||||
}
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"myInt": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"myBool": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"myNullableEnum": true,
|
||||
"myInnerStruct": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"my_map": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"my_vec": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"my_empty_map": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"my_empty_vec": {
|
||||
"type": "array",
|
||||
"items": true
|
||||
},
|
||||
"my_tuple": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "string",
|
||||
"maxLength": 1,
|
||||
"minLength": 1
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
}
|
||||
],
|
||||
"maxItems": 2,
|
||||
"minItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
80
schemars/tests/expected/from_value_openapi3.json
Normal file
80
schemars/tests/expected/from_value_openapi3.json
Normal file
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "MyStruct",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"myInt": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"myBool": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"myNullableEnum": {
|
||||
"nullable": true
|
||||
},
|
||||
"myInnerStruct": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"my_map": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"my_vec": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"my_empty_map": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"my_empty_vec": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
"my_tuple": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "string",
|
||||
"maxLength": 1,
|
||||
"minLength": 1
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
}
|
||||
],
|
||||
"maxItems": 2,
|
||||
"minItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"myBool": true,
|
||||
"myInnerStruct": {
|
||||
"my_empty_map": {},
|
||||
"my_empty_vec": [],
|
||||
"my_map": {
|
||||
"": 0.0
|
||||
},
|
||||
"my_tuple": [
|
||||
"💩",
|
||||
42
|
||||
],
|
||||
"my_vec": [
|
||||
"hello",
|
||||
"world"
|
||||
]
|
||||
},
|
||||
"myInt": 123,
|
||||
"myNullableEnum": null
|
||||
}
|
||||
}
|
77
schemars/tests/from_value.rs
Normal file
77
schemars/tests/from_value.rs
Normal file
|
@ -0,0 +1,77 @@
|
|||
mod util;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use schemars::gen::SchemaSettings;
|
||||
use serde::Serialize;
|
||||
use util::*;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MyStruct {
|
||||
pub my_int: i32,
|
||||
pub my_bool: bool,
|
||||
pub my_nullable_enum: Option<MyEnum>,
|
||||
pub my_inner_struct: MyInnerStruct,
|
||||
#[serde(skip)]
|
||||
pub skip: i32,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub skip_if_none: Option<MyEnum>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct MyInnerStruct {
|
||||
pub my_map: HashMap<String, f64>,
|
||||
pub my_vec: Vec<&'static str>,
|
||||
pub my_empty_map: HashMap<String, f64>,
|
||||
pub my_empty_vec: Vec<&'static str>,
|
||||
pub my_tuple: (char, u8),
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub enum MyEnum {
|
||||
StringNewType(String),
|
||||
StructVariant { floats: Vec<f32> },
|
||||
}
|
||||
|
||||
fn make_value() -> MyStruct {
|
||||
let mut value = MyStruct {
|
||||
my_int: 123,
|
||||
my_bool: true,
|
||||
my_nullable_enum: None,
|
||||
my_inner_struct: MyInnerStruct {
|
||||
my_map: HashMap::new(),
|
||||
my_vec: vec!["hello", "world"],
|
||||
my_empty_map: HashMap::new(),
|
||||
my_empty_vec: vec![],
|
||||
my_tuple: ('💩', 42),
|
||||
},
|
||||
skip: 123,
|
||||
skip_if_none: None,
|
||||
};
|
||||
value.my_inner_struct.my_map.insert(String::new(), 0.0);
|
||||
value
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn schema_from_value_matches_draft07() -> TestResult {
|
||||
let gen = SchemaSettings::draft07().into_generator();
|
||||
let actual = gen.into_root_schema_for_value(&make_value())?;
|
||||
|
||||
test_schema(&actual, "from_value_draft07")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn schema_from_value_matches_2019_09() -> TestResult {
|
||||
let gen = SchemaSettings::draft2019_09().into_generator();
|
||||
let actual = gen.into_root_schema_for_value(&make_value())?;
|
||||
|
||||
test_schema(&actual, "from_value_2019_09")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn schema_from_value_matches_openapi3() -> TestResult {
|
||||
let gen = SchemaSettings::openapi3().into_generator();
|
||||
let actual = gen.into_root_schema_for_value(&make_value())?;
|
||||
|
||||
test_schema(&actual, "from_value_openapi3")
|
||||
}
|
5
schemars/tests/ui/schema_for_arg_value.rs
Normal file
5
schemars/tests/ui/schema_for_arg_value.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
use schemars::schema_for;
|
||||
|
||||
fn main() {
|
||||
let _schema = schema_for!(123);
|
||||
}
|
7
schemars/tests/ui/schema_for_arg_value.stderr
Normal file
7
schemars/tests/ui/schema_for_arg_value.stderr
Normal file
|
@ -0,0 +1,7 @@
|
|||
error: This argument to `schema_for!` is not a type - did you mean to use `schema_for_value!` instead?
|
||||
--> $DIR/schema_for_arg_value.rs:4:19
|
||||
|
|
||||
4 | let _schema = schema_for!(123);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
@ -18,7 +18,7 @@ pub fn test_default_generated_schema<T: JsonSchema>(file: &str) -> TestResult {
|
|||
test_schema(&actual, file)
|
||||
}
|
||||
|
||||
fn test_schema(actual: &RootSchema, file: &str) -> TestResult {
|
||||
pub fn test_schema(actual: &RootSchema, file: &str) -> TestResult {
|
||||
let expected_json = match fs::read_to_string(format!("tests/expected/{}.json", file)) {
|
||||
Ok(j) => j,
|
||||
Err(e) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue