diff --git a/schemars/tests/expected/struct-newtype.json b/schemars/tests/expected/struct-newtype.json new file mode 100644 index 0000000..60a0273 --- /dev/null +++ b/schemars/tests/expected/struct-newtype.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Newtype", + "type": "integer" +} \ No newline at end of file diff --git a/schemars/tests/expected/struct-normal.json b/schemars/tests/expected/struct-normal.json new file mode 100644 index 0000000..f3fdf58 --- /dev/null +++ b/schemars/tests/expected/struct-normal.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Struct", + "type": "object", + "properties": { + "bar": { + "type": "boolean" + }, + "foo": { + "type": "integer" + } + }, + "required": [ + "bar", + "foo" + ] +} \ No newline at end of file diff --git a/schemars/tests/expected/struct-tuple.json b/schemars/tests/expected/struct-tuple.json new file mode 100644 index 0000000..e3bb6e2 --- /dev/null +++ b/schemars/tests/expected/struct-tuple.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Tuple", + "type": "array", + "items": [ + { + "type": "integer" + }, + { + "type": "boolean" + } + ], + "maxItems": 2, + "minItems": 2 +} \ No newline at end of file diff --git a/schemars/tests/expected/struct-unit.json b/schemars/tests/expected/struct-unit.json new file mode 100644 index 0000000..3252d20 --- /dev/null +++ b/schemars/tests/expected/struct-unit.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Unit", + "type": "null" +} \ No newline at end of file diff --git a/schemars/tests/struct.rs b/schemars/tests/struct.rs new file mode 100644 index 0000000..4082ed8 --- /dev/null +++ b/schemars/tests/struct.rs @@ -0,0 +1,38 @@ +mod util; +use schemars::JsonSchema; +use util::*; + +#[derive(Debug, JsonSchema)] +pub struct Struct { + foo: i32, + bar: bool, +} + +#[test] +fn struct_normal() -> TestResult { + test_default_generated_schema::("struct-normal") +} + +#[derive(Debug, JsonSchema)] +pub struct Tuple(i32, bool); + +#[test] +fn struct_tuple() -> TestResult { + test_default_generated_schema::("struct-tuple") +} + +#[derive(Debug, JsonSchema)] +pub struct Newtype(i32); + +#[test] +fn struct_newtype() -> TestResult { + test_default_generated_schema::("struct-newtype") +} + +#[derive(Debug, JsonSchema)] +pub struct Unit; + +#[test] +fn struct_unit() -> TestResult { + test_default_generated_schema::("struct-unit") +} diff --git a/schemars_derive/src/lib.rs b/schemars_derive/src/lib.rs index b45ddf2..37a24ed 100644 --- a/schemars_derive/src/lib.rs +++ b/schemars_derive/src/lib.rs @@ -28,9 +28,11 @@ pub fn derive_json_schema(input: proc_macro::TokenStream) -> proc_macro::TokenSt } let schema = match cont.data { + Data::Struct(Style::Unit, _) => schema_for_unit_struct(), + Data::Struct(Style::Newtype, ref fields) => schema_for_newtype_struct(&fields[0]), + Data::Struct(Style::Tuple, ref fields) => schema_for_tuple_struct(fields), Data::Struct(Style::Struct, ref fields) => schema_for_struct(fields, &cont.attrs), Data::Enum(ref variants) => schema_for_enum(variants, &cont.attrs), - _ => unimplemented!("work in progress!"), }; let type_name = cont.ident; @@ -105,7 +107,7 @@ fn schema_for_enum(variants: &[Variant], cattrs: &attr::Container) -> TokenStrea EnumTag::External => schema_for_external_tagged_enum(variants, cattrs), EnumTag::None => schema_for_untagged_enum(variants, cattrs), EnumTag::Internal { tag } => schema_for_internal_tagged_enum(variants, cattrs, tag), - EnumTag::Adjacent => unimplemented!("Adjacent tagged enums not yet supported."), + EnumTag::Adjacent { .. } => unimplemented!("Adjacent tagged enums not yet supported."), } } @@ -204,26 +206,33 @@ fn schema_for_untagged_enum(variants: &[Variant], cattrs: &attr::Container) -> T fn schema_for_untagged_enum_variant(variant: &Variant, cattrs: &attr::Container) -> TokenStream { match variant.style { - Style::Unit => quote! { - gen.subschema_for::<()>()? - }, - Style::Newtype => { - let f = &variant.fields[0]; - let ty = f.ty; - quote_spanned! {f.original.span()=> - gen.subschema_for::<#ty>()? - } - } - Style::Tuple => { - let types = variant.fields.iter().map(|f| f.ty); - quote! { - gen.subschema_for::<(#(#types),*)>()? - } - } + Style::Unit => schema_for_unit_struct(), + Style::Newtype => schema_for_newtype_struct(&variant.fields[0]), + Style::Tuple => schema_for_tuple_struct(&variant.fields), Style::Struct => schema_for_struct(&variant.fields, cattrs), } } +fn schema_for_unit_struct() -> TokenStream { + quote! { + gen.subschema_for::<()>()? + } +} + +fn schema_for_newtype_struct(field: &Field) -> TokenStream { + let ty = field.ty; + quote_spanned! {field.original.span()=> + gen.subschema_for::<#ty>()? + } +} + +fn schema_for_tuple_struct(fields: &[Field]) -> TokenStream { + let types = fields.iter().map(|f| f.ty); + quote! { + gen.subschema_for::<(#(#types),*)>()? + } +} + fn schema_for_struct(fields: &[Field], cattrs: &attr::Container) -> TokenStream { let (nested, flat): (Vec<_>, Vec<_>) = fields.iter().partition(|f| !f.attrs.flatten()); let container_has_default = has_default(cattrs.default());