Attribute for defining examples (#23)
This commit is contained in:
parent
19b9bef395
commit
e259955809
4 changed files with 88 additions and 3 deletions
25
schemars/tests/examples.rs
Normal file
25
schemars/tests/examples.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
mod util;
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::Serialize;
|
||||||
|
use util::*;
|
||||||
|
|
||||||
|
#[derive(Default, Debug, JsonSchema, Serialize)]
|
||||||
|
#[schemars(example = "Struct::default", example = "null")]
|
||||||
|
pub struct Struct {
|
||||||
|
#[schemars(example = "eight", example = "null")]
|
||||||
|
foo: i32,
|
||||||
|
bar: bool,
|
||||||
|
#[schemars(example = "null")]
|
||||||
|
baz: Option<&'static str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eight() -> i32 {
|
||||||
|
8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn null() -> () {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn examples() -> TestResult {
|
||||||
|
test_default_generated_schema::<Struct>("examples")
|
||||||
|
}
|
39
schemars/tests/expected/examples.json
Normal file
39
schemars/tests/expected/examples.json
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "Struct",
|
||||||
|
"examples": [
|
||||||
|
{
|
||||||
|
"bar": false,
|
||||||
|
"baz": null,
|
||||||
|
"foo": 0
|
||||||
|
},
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"bar",
|
||||||
|
"foo"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"bar": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"baz": {
|
||||||
|
"examples": [
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"foo": {
|
||||||
|
"examples": [
|
||||||
|
8,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ pub struct Attrs {
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub deprecated: bool,
|
pub deprecated: bool,
|
||||||
// TODO pub example: Option<syn::Path>,
|
pub examples: Vec<syn::Path>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -111,6 +111,12 @@ impl Attrs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Meta(NameValue(m)) if m.path.is_ident("example") => {
|
||||||
|
if let Ok(fun) = parse_lit_into_path(errors, attr_type, "example", &m.lit) {
|
||||||
|
self.examples.push(fun)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Meta(_meta_item) => {
|
Meta(_meta_item) => {
|
||||||
// TODO uncomment this for 0.8.0 (breaking change)
|
// TODO uncomment this for 0.8.0 (breaking change)
|
||||||
// https://github.com/GREsau/schemars/issues/18
|
// https://github.com/GREsau/schemars/issues/18
|
||||||
|
|
|
@ -3,13 +3,14 @@ use attr::Attrs;
|
||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::{ToTokens, TokenStreamExt};
|
use quote::{ToTokens, TokenStreamExt};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SchemaMetadata<'a> {
|
pub struct SchemaMetadata<'a> {
|
||||||
pub title: Option<&'a str>,
|
pub title: Option<&'a str>,
|
||||||
pub description: Option<&'a str>,
|
pub description: Option<&'a str>,
|
||||||
pub deprecated: bool,
|
pub deprecated: bool,
|
||||||
pub read_only: bool,
|
pub read_only: bool,
|
||||||
pub write_only: bool,
|
pub write_only: bool,
|
||||||
|
pub examples: &'a [syn::Path],
|
||||||
pub default: Option<TokenStream>,
|
pub default: Option<TokenStream>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +37,10 @@ impl<'a> SchemaMetadata<'a> {
|
||||||
title: attrs.title.as_ref().and_then(none_if_empty),
|
title: attrs.title.as_ref().and_then(none_if_empty),
|
||||||
description: attrs.description.as_ref().and_then(none_if_empty),
|
description: attrs.description.as_ref().and_then(none_if_empty),
|
||||||
deprecated: attrs.deprecated,
|
deprecated: attrs.deprecated,
|
||||||
..Default::default()
|
examples: &attrs.examples,
|
||||||
|
read_only: false,
|
||||||
|
write_only: false,
|
||||||
|
default: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +84,17 @@ impl<'a> SchemaMetadata<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.examples.is_empty() {
|
||||||
|
let examples = self.examples.iter().map(|eg| {
|
||||||
|
quote! {
|
||||||
|
schemars::_serde_json::value::to_value(#eg())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setters.push(quote! {
|
||||||
|
metadata.examples = vec![#(#examples),*].into_iter().flatten().collect();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(default) = &self.default {
|
if let Some(default) = &self.default {
|
||||||
setters.push(quote! {
|
setters.push(quote! {
|
||||||
metadata.default = #default.and_then(|d| schemars::_serde_json::value::to_value(d).ok());
|
metadata.default = #default.and_then(|d| schemars::_serde_json::value::to_value(d).ok());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue