parent
8207892fa6
commit
11b7a09c93
4 changed files with 235 additions and 3 deletions
|
@ -59,3 +59,19 @@ pub enum Untagged {
|
||||||
fn enum_untagged() -> TestResult {
|
fn enum_untagged() -> TestResult {
|
||||||
test_default_generated_schema::<Untagged>("enum-untagged")
|
test_default_generated_schema::<Untagged>("enum-untagged")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, JsonSchema)]
|
||||||
|
#[schemars(tag = "t", content = "c")]
|
||||||
|
pub enum Adjacent {
|
||||||
|
UnitOne,
|
||||||
|
StringMap(Map<String, String>),
|
||||||
|
UnitStructNewType(UnitStruct),
|
||||||
|
StructNewType(Struct),
|
||||||
|
Struct { foo: i32, bar: bool },
|
||||||
|
Tuple(i32, bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enum_adjacent_tagged() -> TestResult {
|
||||||
|
test_default_generated_schema::<Adjacent>("enum_adjacent_tagged-untagged")
|
||||||
|
}
|
||||||
|
|
150
schemars/tests/expected/enum_adjacent_tagged-untagged.json
Normal file
150
schemars/tests/expected/enum_adjacent_tagged-untagged.json
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "Adjacent",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"t"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"t": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"UnitOne"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"c",
|
||||||
|
"t"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"c": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"t": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"StringMap"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"c",
|
||||||
|
"t"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"c": {
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
"t": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"UnitStructNewType"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"c",
|
||||||
|
"t"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"c": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"bar",
|
||||||
|
"foo"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"bar": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"foo": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"t": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"StructNewType"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"c",
|
||||||
|
"t"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"c": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"bar",
|
||||||
|
"foo"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"bar": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"foo": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"t": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Struct"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"c",
|
||||||
|
"t"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"c": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxItems": 2,
|
||||||
|
"minItems": 2
|
||||||
|
},
|
||||||
|
"t": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Tuple"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -11,8 +11,7 @@ static SERDE_KEYWORDS: &[&str] = &[
|
||||||
// TODO: for structs with `deny_unknown_fields`, set schema's `additionalProperties` to false.
|
// TODO: for structs with `deny_unknown_fields`, set schema's `additionalProperties` to false.
|
||||||
// "deny_unknown_fields",
|
// "deny_unknown_fields",
|
||||||
"tag",
|
"tag",
|
||||||
// TODO: support adjecently tagged enums (https://github.com/GREsau/schemars/issues/4)
|
"content",
|
||||||
// "content",
|
|
||||||
"untagged",
|
"untagged",
|
||||||
"default",
|
"default",
|
||||||
"skip",
|
"skip",
|
||||||
|
|
|
@ -131,7 +131,9 @@ fn schema_for_enum(variants: &[Variant], cattrs: &serde_attr::Container) -> Toke
|
||||||
TagType::External => schema_for_external_tagged_enum(variants),
|
TagType::External => schema_for_external_tagged_enum(variants),
|
||||||
TagType::None => schema_for_untagged_enum(variants),
|
TagType::None => schema_for_untagged_enum(variants),
|
||||||
TagType::Internal { tag } => schema_for_internal_tagged_enum(variants, tag),
|
TagType::Internal { tag } => schema_for_internal_tagged_enum(variants, tag),
|
||||||
TagType::Adjacent { .. } => unimplemented!("Adjacent tagged enums not yet supported."),
|
TagType::Adjacent { tag, content } => {
|
||||||
|
schema_for_adjacent_tagged_enum(variants, tag, content)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +270,71 @@ fn schema_for_untagged_enum_variant(variant: &Variant) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn schema_for_adjacent_tagged_enum<'a>(
|
||||||
|
variants: impl Iterator<Item = &'a Variant<'a>>,
|
||||||
|
tag_name: &str,
|
||||||
|
content_name: &str,
|
||||||
|
) -> TokenStream {
|
||||||
|
let schemas = variants.map(|variant| {
|
||||||
|
let content_schema = match variant.style {
|
||||||
|
Style::Unit => None,
|
||||||
|
Style::Newtype => {
|
||||||
|
let field = &variant.fields[0];
|
||||||
|
let ty = get_json_schema_type(field);
|
||||||
|
Some(quote_spanned! {field.original.span()=>
|
||||||
|
<#ty>::json_schema(gen)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Style::Struct => Some(schema_for_struct(&variant.fields, None)),
|
||||||
|
Style::Tuple => Some(schema_for_tuple_struct(&variant.fields)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let (add_content_property, add_content_required) = content_schema
|
||||||
|
.map(|content_schema| {
|
||||||
|
(
|
||||||
|
quote!(props.insert(#content_name.to_owned(), #content_schema);),
|
||||||
|
quote!(required.insert(#content_name.to_owned());),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let name = variant.attrs.name().deserialize_name();
|
||||||
|
let tag_schema = wrap_schema_fields(quote! {
|
||||||
|
instance_type: Some(schemars::schema::InstanceType::String.into()),
|
||||||
|
enum_values: Some(vec![#name.into()]),
|
||||||
|
});
|
||||||
|
|
||||||
|
let outer_schema = wrap_schema_fields(quote! {
|
||||||
|
instance_type: Some(schemars::schema::InstanceType::Object.into()),
|
||||||
|
object: Some(Box::new(schemars::schema::ObjectValidation {
|
||||||
|
properties: {
|
||||||
|
let mut props = schemars::Map::new();
|
||||||
|
props.insert(#tag_name.to_owned(), #tag_schema);
|
||||||
|
#add_content_property
|
||||||
|
props
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
let mut required = schemars::Set::new();
|
||||||
|
required.insert(#tag_name.to_owned());
|
||||||
|
#add_content_required
|
||||||
|
required
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
let doc_metadata = SchemaMetadata::from_doc_attrs(&variant.original.attrs);
|
||||||
|
doc_metadata.apply_to_schema(outer_schema)
|
||||||
|
});
|
||||||
|
|
||||||
|
wrap_schema_fields(quote! {
|
||||||
|
subschemas: Some(Box::new(schemars::schema::SubschemaValidation {
|
||||||
|
any_of: Some(vec![#(#schemas),*]),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn schema_for_unit_struct() -> TokenStream {
|
fn schema_for_unit_struct() -> TokenStream {
|
||||||
quote! {
|
quote! {
|
||||||
gen.subschema_for::<()>()
|
gen.subschema_for::<()>()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue