mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-12 09:41:02 +00:00
Add `#[serde(skip_serializing)] to skip serializing some fields
Closes #99
This commit is contained in:
@@ -16,14 +16,20 @@ pub enum FieldNames {
|
|||||||
|
|
||||||
/// Represents field attribute information
|
/// Represents field attribute information
|
||||||
pub struct FieldAttrs {
|
pub struct FieldAttrs {
|
||||||
|
skip_serializing_field: bool,
|
||||||
names: FieldNames,
|
names: FieldNames,
|
||||||
use_default: bool,
|
use_default: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FieldAttrs {
|
impl FieldAttrs {
|
||||||
/// Create a FieldAttr with a single default field name
|
/// Create a FieldAttr with a single default field name
|
||||||
pub fn new(default_value: bool, name: P<ast::Expr>) -> FieldAttrs {
|
pub fn new(
|
||||||
|
skip_serializing_field: bool,
|
||||||
|
default_value: bool,
|
||||||
|
name: P<ast::Expr>,
|
||||||
|
) -> FieldAttrs {
|
||||||
FieldAttrs {
|
FieldAttrs {
|
||||||
|
skip_serializing_field: skip_serializing_field,
|
||||||
names: FieldNames::Global(name),
|
names: FieldNames::Global(name),
|
||||||
use_default: default_value,
|
use_default: default_value,
|
||||||
}
|
}
|
||||||
@@ -31,12 +37,14 @@ impl FieldAttrs {
|
|||||||
|
|
||||||
/// Create a FieldAttr with format specific field names
|
/// Create a FieldAttr with format specific field names
|
||||||
pub fn new_with_formats(
|
pub fn new_with_formats(
|
||||||
|
skip_serializing_field: bool,
|
||||||
default_value: bool,
|
default_value: bool,
|
||||||
default_name: P<ast::Expr>,
|
default_name: P<ast::Expr>,
|
||||||
formats: HashMap<P<ast::Expr>, P<ast::Expr>>,
|
formats: HashMap<P<ast::Expr>, P<ast::Expr>>,
|
||||||
) -> FieldAttrs {
|
) -> FieldAttrs {
|
||||||
FieldAttrs {
|
FieldAttrs {
|
||||||
names: FieldNames::Format {
|
skip_serializing_field: skip_serializing_field,
|
||||||
|
names: FieldNames::Format {
|
||||||
formats: formats,
|
formats: formats,
|
||||||
default: default_name,
|
default: default_name,
|
||||||
},
|
},
|
||||||
@@ -104,4 +112,9 @@ impl FieldAttrs {
|
|||||||
pub fn use_default(&self) -> bool {
|
pub fn use_default(&self) -> bool {
|
||||||
self.use_default
|
self.use_default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Predicate for ignoring a field when serializing a value
|
||||||
|
pub fn skip_serializing_field(&self) -> bool {
|
||||||
|
self.skip_serializing_field
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -483,6 +483,7 @@ fn deserialize_item_enum(
|
|||||||
enum_def.variants.iter()
|
enum_def.variants.iter()
|
||||||
.map(|variant|
|
.map(|variant|
|
||||||
attr::FieldAttrs::new(
|
attr::FieldAttrs::new(
|
||||||
|
false,
|
||||||
true,
|
true,
|
||||||
builder.expr().str(variant.node.name)))
|
builder.expr().str(variant.node.name)))
|
||||||
.collect()
|
.collect()
|
||||||
|
|||||||
+24
-10
@@ -58,10 +58,18 @@ fn default_value(mi: &ast::MetaItem) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn skip_serializing_field(mi: &ast::MetaItem) -> bool {
|
||||||
|
if let ast::MetaItem_::MetaWord(ref n) = mi.node {
|
||||||
|
n == &"skip_serializing"
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn field_attrs<'a>(
|
fn field_attrs<'a>(
|
||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
field: &'a ast::StructField,
|
field: &'a ast::StructField,
|
||||||
) -> (Rename<'a>, bool) {
|
) -> (Rename<'a>, bool, bool) {
|
||||||
field.node.attrs.iter()
|
field.node.attrs.iter()
|
||||||
.find(|sa| {
|
.find(|sa| {
|
||||||
if let ast::MetaList(ref n, _) = sa.node.value.node {
|
if let ast::MetaList(ref n, _) = sa.node.value.node {
|
||||||
@@ -73,15 +81,18 @@ fn field_attrs<'a>(
|
|||||||
.and_then(|sa| {
|
.and_then(|sa| {
|
||||||
if let ast::MetaList(_, ref vals) = sa.node.value.node {
|
if let ast::MetaList(_, ref vals) = sa.node.value.node {
|
||||||
attr::mark_used(&sa);
|
attr::mark_used(&sa);
|
||||||
Some((vals.iter()
|
Some((
|
||||||
.fold(None, |v, mi| v.or(rename(builder, mi)))
|
vals.iter()
|
||||||
.unwrap_or(Rename::None),
|
.fold(None, |v, mi| v.or(rename(builder, mi)))
|
||||||
vals.iter().any(|mi| default_value(mi))))
|
.unwrap_or(Rename::None),
|
||||||
|
vals.iter().any(|mi| default_value(mi)),
|
||||||
|
vals.iter().any(|mi| skip_serializing_field(mi)),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
Some((Rename::None, false))
|
Some((Rename::None, false, false))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or((Rename::None, false))
|
.unwrap_or((Rename::None, false, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn struct_field_attrs(
|
pub fn struct_field_attrs(
|
||||||
@@ -92,23 +103,26 @@ pub fn struct_field_attrs(
|
|||||||
struct_def.fields.iter()
|
struct_def.fields.iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
match field_attrs(builder, field) {
|
match field_attrs(builder, field) {
|
||||||
(Rename::Global(rename), default_value) =>
|
(Rename::Global(rename), default_value, skip_serializing_field) =>
|
||||||
FieldAttrs::new(
|
FieldAttrs::new(
|
||||||
|
skip_serializing_field,
|
||||||
default_value,
|
default_value,
|
||||||
builder.expr().build_lit(P(rename.clone()))),
|
builder.expr().build_lit(P(rename.clone()))),
|
||||||
(Rename::Format(renames), default_value) => {
|
(Rename::Format(renames), default_value, skip_serializing_field) => {
|
||||||
let mut res = HashMap::new();
|
let mut res = HashMap::new();
|
||||||
res.extend(
|
res.extend(
|
||||||
renames.into_iter()
|
renames.into_iter()
|
||||||
.map(|(k,v)|
|
.map(|(k,v)|
|
||||||
(k, builder.expr().build_lit(P(v.clone())))));
|
(k, builder.expr().build_lit(P(v.clone())))));
|
||||||
FieldAttrs::new_with_formats(
|
FieldAttrs::new_with_formats(
|
||||||
|
skip_serializing_field,
|
||||||
default_value,
|
default_value,
|
||||||
default_field_name(cx, builder, field.node.kind),
|
default_field_name(cx, builder, field.node.kind),
|
||||||
res)
|
res)
|
||||||
},
|
},
|
||||||
(Rename::None, default_value) => {
|
(Rename::None, default_value, skip_serializing_field) => {
|
||||||
FieldAttrs::new(
|
FieldAttrs::new(
|
||||||
|
skip_serializing_field,
|
||||||
default_value,
|
default_value,
|
||||||
default_field_name(cx, builder, field.node.kind))
|
default_field_name(cx, builder, field.node.kind))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -550,6 +550,7 @@ fn serialize_struct_visitor<I>(
|
|||||||
|
|
||||||
let arms: Vec<ast::Arm> = field_attrs.into_iter()
|
let arms: Vec<ast::Arm> = field_attrs.into_iter()
|
||||||
.zip(value_exprs)
|
.zip(value_exprs)
|
||||||
|
.filter(|&(ref field, _)| !field.skip_serializing_field())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (field, value_expr))| {
|
.map(|(i, (field, value_expr))| {
|
||||||
let key_expr = field.serializer_key_expr(cx);
|
let key_expr = field.serializer_key_expr(cx);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::default;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@@ -30,6 +31,12 @@ enum SerEnum<A> {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Deserialize, Serialize)]
|
||||||
|
struct SkipSerializingFields<A: default::Default> {
|
||||||
|
a: i8,
|
||||||
|
#[serde(skip_serializing, default)]
|
||||||
|
b: A,
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default() {
|
fn test_default() {
|
||||||
@@ -71,3 +78,13 @@ fn test_enum_format_rename() {
|
|||||||
let deserialized_value = serde_json::from_str(ans).unwrap();
|
let deserialized_value = serde_json::from_str(ans).unwrap();
|
||||||
assert_eq!(value, deserialized_value);
|
assert_eq!(value, deserialized_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_skip_serializing_fields() {
|
||||||
|
let value = SkipSerializingFields { a: 1, b: 2 };
|
||||||
|
let serialized_value = serde_json::to_string(&value).unwrap();
|
||||||
|
assert_eq!(serialized_value, "{\"a\":1}");
|
||||||
|
|
||||||
|
let deserialized_value: SkipSerializingFields<_> = serde_json::from_str(&serialized_value).unwrap();
|
||||||
|
assert_eq!(SkipSerializingFields { a: 1, b: 0 }, deserialized_value);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user