additionalProperties: false for struct annotated with serde deny_unknown_fields (#30)

Co-authored-by: Denis Kurilov <denis@routinghub.com>
This commit is contained in:
Denis Kurilov 2020-05-16 13:02:47 +02:00 committed by GitHub
parent ea351f3b42
commit 1190b1fad9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 2 deletions

View file

@ -0,0 +1,25 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Struct",
"type": "object",
"additionalProperties": false,
"required": [
"bar",
"foo"
],
"properties": {
"bar": {
"type": "boolean"
},
"baz": {
"type": [
"string",
"null"
]
},
"foo": {
"type": "integer",
"format": "int32"
}
}
}

View file

@ -0,0 +1,16 @@
mod util;
use schemars::JsonSchema;
use util::*;
#[derive(Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct Struct {
foo: i32,
bar: bool,
baz: Option<String>,
}
#[test]
fn struct_normal_additional_properties() -> TestResult {
test_default_generated_schema::<Struct>("struct-normal-additional-properties")
}

View file

@ -8,8 +8,7 @@ use syn::{Attribute, Data, Field, Meta, NestedMeta, Variant};
static SERDE_KEYWORDS: &[&str] = &[ static SERDE_KEYWORDS: &[&str] = &[
"rename", "rename",
"rename_all", "rename_all",
// TODO: for structs with `deny_unknown_fields`, set schema's `additionalProperties` to false. "deny_unknown_fields",
// "deny_unknown_fields",
"tag", "tag",
"content", "content",
"untagged", "untagged",

View file

@ -362,12 +362,23 @@ fn expr_for_struct(fields: &[Field], cattrs: Option<&serde_attr::Container>) ->
}) })
.collect(); .collect();
let deny_unknown_fields = cattrs
.map_or(false, |attrs| attrs.deny_unknown_fields());
quote! { quote! {
{ {
#(#type_defs)* #(#type_defs)*
#set_container_default #set_container_default
let mut schema_object = schemars::schema::SchemaObject { let mut schema_object = schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::Object.into()), instance_type: Some(schemars::schema::InstanceType::Object.into()),
object: Some(Box::new(schemars::schema::ObjectValidation {
additional_properties: if #deny_unknown_fields {
Some(Box::new(false.into()))
} else {
None
},
..Default::default()
})),
..Default::default() ..Default::default()
}; };
#(#properties)* #(#properties)*