Fix skip_serializing_if/serialize_with handling

Previously whenever a field with a default value has both `skip_serializing_if` and `with`/`serialize_with` attributes, the value would be converted to a type that performs the custom serialization before checking if it should be serialized. This would cause the wrong type to be given to the skip_serializing_if function, causing a compile error.

Issue #26
This commit is contained in:
Graham Esau 2020-04-11 22:06:48 +01:00
parent d1f2c0f803
commit 63af0ceb73
7 changed files with 54 additions and 42 deletions

View file

@ -343,12 +343,22 @@ impl SchemaGenerator {
}
}
pub(crate) fn apply_metadata(&self, schema: Schema, metadata: Metadata) -> Schema {
let mut schema_obj = schema.into();
/// This function is only public for use by schemars_derive.
///
/// It should not be considered part of the public API.
#[doc(hidden)]
pub fn apply_metadata(&self, schema: Schema, metadata: Option<Metadata>) -> Schema {
match metadata {
None => return schema,
Some(metadata) if metadata == Metadata::default() => return schema,
Some(metadata) => {
let mut schema_obj = schema.into();
self.make_extensible(&mut schema_obj);
schema_obj.metadata = Some(Box::new(metadata)).merge(schema_obj.metadata);
self.make_extensible(&mut schema_obj);
schema_obj.metadata = Some(Box::new(metadata)).merge(schema_obj.metadata);
Schema::Object(schema_obj)
Schema::Object(schema_obj)
}
}
}
}

View file

@ -65,10 +65,7 @@ impl<T: JsonSchema> JsonSchema for Option<T> {
_required: bool,
) {
let mut schema = gen.subschema_for::<Self>();
if let Some(metadata) = metadata {
schema = gen.apply_metadata(schema, metadata);
}
schema = gen.apply_metadata(schema, metadata);
let object = parent.object();
object.properties.insert(name, schema);

View file

@ -300,10 +300,7 @@ pub trait JsonSchema {
required: bool,
) {
let mut schema = gen.subschema_for::<Self>();
if let Some(metadata) = metadata {
schema = gen.apply_metadata(schema, metadata);
}
schema = gen.apply_metadata(schema, metadata);
let object = parent.object();
if required {

View file

@ -3,6 +3,10 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use util::*;
fn is_default<T: Default + PartialEq>(value: &T) -> bool {
value == &T::default()
}
fn ten_and_true() -> MyStruct2 {
MyStruct2 {
my_int: 10,
@ -28,9 +32,14 @@ pub struct MyStruct {
pub my_bool: bool,
#[serde(serialize_with = "custom_serialize")]
pub my_struct2: MyStruct2,
#[serde(
serialize_with = "custom_serialize",
skip_serializing_if = "is_default"
)]
pub my_struct2_default_skipped: MyStruct2,
}
#[derive(Default, Deserialize, Serialize, JsonSchema, Debug)]
#[derive(Default, Deserialize, Serialize, JsonSchema, Debug, PartialEq)]
#[serde(default = "ten_and_true")]
pub struct MyStruct2 {
#[serde(default = "six")]

View file

@ -19,6 +19,9 @@
"$ref": "#/definitions/MyStruct2"
}
]
},
"my_struct2_default_skipped": {
"$ref": "#/definitions/MyStruct2"
}
},
"definitions": {