Add more info to README

This commit is contained in:
Graham Esau 2019-10-22 22:49:24 +01:00
parent 5c307b92fb
commit 792fbbb86e
7 changed files with 182 additions and 91 deletions

190
README.md
View file

@ -1,4 +1,4 @@
# schemars # Schemars
[![Travis (.org)](https://img.shields.io/travis/GREsau/schemars?logo=travis)](https://travis-ci.org/GREsau/schemars) [![Travis (.org)](https://img.shields.io/travis/GREsau/schemars?logo=travis)](https://travis-ci.org/GREsau/schemars)
[![Crates.io](https://img.shields.io/crates/v/schemars)](https://crates.io/crates/schemars) [![Crates.io](https://img.shields.io/crates/v/schemars)](https://crates.io/crates/schemars)
@ -9,97 +9,175 @@ Work in progress!
## Basic Usage ## Basic Usage
If you don't really care about the specifics, the easiest way to generate a JSON schema for you types is to `#[derive(JsonSchema)]` and use the `schema_for!` macro:
```rust
use schemars::{schema_for, JsonSchema};
#[derive(JsonSchema)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(JsonSchema)]
pub enum MyEnum {
Unit,
StringNewType(String)
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}
```
<details>
<summary>Click to see the output JSON schema...</summary>
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"definitions": {
"MyEnum": {
"anyOf": [
{
"enum": [
"Unit"
]
},
{
"type": "object",
"required": [
"StringNewType"
],
"properties": {
"StringNewType": {
"type": "string"
}
}
}
]
}
},
"type": "object",
"required": [
"my_bool",
"my_int",
"my_nullable_enum"
],
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer",
"format": "int32"
},
"my_nullable_enum": {
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
}
}
}
```
</details>
### Serde Compatibility
One of the main aims of this library is compatibility with [serde](https://github.com/serde-rs/serde). Any generated schema *should* match how [serde_json](https://github.com/serde-rs/json) would serialize/deserialize to/from JSON. To support this, Schemars will check for any `#[serde(...)]` attributes on types that derive `JsonSchema`, and adjust the generated schema accordingly.
```rust ```rust
use schemars::{schema_for, JsonSchema}; use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, JsonSchema)] #[derive(Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct MyStruct { pub struct MyStruct {
my_int: i32, #[serde(rename = "myNumber")]
my_nullable: Option<bool>, pub my_int: i32,
my_nested_struct: Nested, pub my_bool: bool,
#[serde(default)]
pub my_nullable_enum: Option<MyEnum>,
} }
#[derive(Deserialize, Serialize, JsonSchema)] #[derive(Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(untagged)]
struct Nested { pub enum MyEnum {
#[serde(default)] Unit,
my_string: String, StringNewType(String)
#[serde(rename = "myArray")]
my_float_vec: Vec<f32>,
my_recursive_struct: Option<Box<Nested>>,
} }
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() {
let schema = schema_for!(MyStruct); let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema)?); println!("{}", serde_json::to_string_pretty(&schema).unwrap());
Ok(())
} }
``` ```
This outputs the following: <details>
<summary>Click to see the output JSON schema...</summary>
```json ```json
{ {
"$schema": "http://json-schema.org/draft-07/schema#", "$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct", "title": "MyStruct",
"type": "object",
"definitions": { "definitions": {
"Nested": { "MyEnum": {
"type": "object", "anyOf": [
"required": [ {
"myArray", "type": "null"
"myRecursiveStruct"
],
"properties": {
"myArray": {
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}, },
"myRecursiveStruct": { {
"anyOf": [
{
"$ref": "#/definitions/Nested"
},
{
"type": "null"
}
]
},
"myString": {
"type": "string" "type": "string"
} }
} ]
} }
}, },
"type": "object",
"required": [ "required": [
"myInt", "myBool",
"myNestedStruct", "myNumber"
"myNullable"
], ],
"properties": { "properties": {
"myInt": { "myBool": {
"type": "boolean"
},
"myNullableEnum": {
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
},
"myNumber": {
"type": "integer", "type": "integer",
"format": "int32" "format": "int32"
},
"myNestedStruct": {
"$ref": "#/definitions/Nested"
},
"myNullable": {
"type": [
"boolean",
"null"
]
} }
} }
} }
``` ```
</details>
Note that the `#[serde(...)]` attributes are respected. `#[serde(...)]` attributes can be overriden using `#[schemars(...)]` attributes, which behave identically (e.g. `#[schemars(rename_all = "camelCase")]`). You may find this useful if you want to change the generated schema without affecting Serde, or if you're just not using Serde.
## Feature Flags
- `chrono` - implements `JsonSchema` for all [Chrono](https://github.com/chronotope/chrono) types which are serializable by Serde.
- `derive_json_schema` - implements `JsonSchema` for Schemars types themselves
## Customizing Schema Generation
TODO document!
## TODO ## TODO
- Documentation - Documentation

19
schemars/examples/main.rs Normal file
View file

@ -0,0 +1,19 @@
use schemars::{schema_for, JsonSchema};
#[derive(JsonSchema)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(JsonSchema)]
pub enum MyEnum {
Unit,
StringNewType(String)
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,24 @@
use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct MyStruct {
#[serde(rename = "myNumber")]
pub my_int: i32,
pub my_bool: bool,
#[serde(default)]
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(untagged)]
pub enum MyEnum {
Unit,
StringNewType(String)
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -1,26 +0,0 @@
use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
struct MyStruct {
my_int: i32,
my_nullable: Option<bool>,
my_nested_struct: Nested,
}
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
struct Nested {
#[serde(default)]
my_string: String,
#[serde(rename = "myArray")]
my_float_vec: Vec<f32>,
my_recursive_struct: Option<Box<Nested>>,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema)?);
Ok(())
}

View file

@ -1,7 +1,7 @@
use crate::schema::*; use crate::schema::*;
use crate::{JsonSchema, Map}; use crate::{JsonSchema, Map};
/// Settings to customize how a Schema is generated. /// Settings to customize how Schemas are generated.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct SchemaSettings { pub struct SchemaSettings {
/// If `true`, schemas for [`Option<T>`](Option) will include a `nullable` property. /// If `true`, schemas for [`Option<T>`](Option) will include a `nullable` property.
@ -37,16 +37,11 @@ pub enum BoolSchemas {
impl Default for SchemaSettings { impl Default for SchemaSettings {
fn default() -> SchemaSettings { fn default() -> SchemaSettings {
SchemaSettings::new() SchemaSettings::draft07()
} }
} }
impl SchemaSettings { impl SchemaSettings {
/// Creates `SchemaSettings` that conform to [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7).
pub fn new() -> SchemaSettings {
Self::draft07()
}
/// Creates `SchemaSettings` that conform to [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7). /// Creates `SchemaSettings` that conform to [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7).
pub fn draft07() -> SchemaSettings { pub fn draft07() -> SchemaSettings {
SchemaSettings { SchemaSettings {
@ -57,7 +52,7 @@ impl SchemaSettings {
} }
} }
/// Creates `SchemaSettings` that conform to [OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject). /// Creates `SchemaSettings` that conform to [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject).
pub fn openapi3() -> SchemaSettings { pub fn openapi3() -> SchemaSettings {
SchemaSettings { SchemaSettings {
option_nullable: true, option_nullable: true,

View file

@ -1,3 +1,4 @@
#[cfg(feature = "derive_json_schema")]
use crate as schemars; use crate as schemars;
#[cfg(feature = "derive_json_schema")] #[cfg(feature = "derive_json_schema")]
use crate::JsonSchema; use crate::JsonSchema;

View file

@ -199,7 +199,7 @@ fn schema_for_internal_tagged_enum<'a>(
let field = &variant.fields[0]; let field = &variant.fields[0];
let ty = get_json_schema_type(field); let ty = get_json_schema_type(field);
quote_spanned! {field.original.span()=> quote_spanned! {field.original.span()=>
<#ty>::json_schema(gen) gen.subschema_for::<#ty>()
} }
} }
Style::Struct => schema_for_struct(&variant.fields, cattrs), Style::Struct => schema_for_struct(&variant.fields, cattrs),