mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 04:48:01 +00:00
Implement serialize_with for variants
As discussed in #1013, serialize_with functions attached to variants receive an argument for each inner value contained within the variant. Internally such a function is wired up to the serializer as if the variant were a newtype variant.
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: variant `Newtype` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing)]
|
||||
enum Enum {
|
||||
#[serde(serialize_with = "serialize_some_newtype_variant")]
|
||||
Newtype(#[serde(skip_serializing)] String),
|
||||
}
|
||||
|
||||
fn serialize_some_newtype_variant<S>(_: &String) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: variant `Newtype` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing_if)]
|
||||
enum Enum {
|
||||
#[serde(serialize_with = "serialize_some_newtype_variant")]
|
||||
Newtype(#[serde(skip_serializing_if = "always")] String),
|
||||
}
|
||||
|
||||
fn serialize_some_newtype_variant<S>(_: &String) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn always<T>(_: &T) -> bool { true }
|
||||
|
||||
fn main() { }
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: variant `Struct` cannot have both #[serde(serialize_with)] and a field `f1` marked with #[serde(skip_serializing)]
|
||||
enum Enum {
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
Struct {
|
||||
#[serde(skip_serializing)]
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
}
|
||||
|
||||
fn serialize_some_other_variant<S>(_: &String, _: Option<&u8>, _: S) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: variant `Struct` cannot have both #[serde(serialize_with)] and a field `f1` marked with #[serde(skip_serializing_if)]
|
||||
enum Enum {
|
||||
#[serde(serialize_with = "serialize_some_newtype_variant")]
|
||||
Struct {
|
||||
#[serde(skip_serializing_if = "always")]
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
}
|
||||
|
||||
fn serialize_some_other_variant<S>(_: &String, _: Option<&u8>, _: S) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn always<T>(_: &T) -> bool { true }
|
||||
|
||||
fn main() { }
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: variant `Tuple` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing)]
|
||||
enum Enum {
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
Tuple(#[serde(skip_serializing)] String, u8),
|
||||
}
|
||||
|
||||
fn serialize_some_other_variant<S>(_: &String, _: Option<&u8>, _: S) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: variant `Tuple` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing_if)]
|
||||
enum Enum {
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
Tuple(#[serde(skip_serializing_if = "always")] String, u8),
|
||||
}
|
||||
|
||||
fn serialize_some_other_variant<S>(_: &String, _: Option<&u8>, _: S) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn always<T>(_: &T) -> bool { true }
|
||||
|
||||
fn main() { }
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: variant `Unit` cannot have both #[serde(serialize_with)] and #[serde(skip_serializing)]
|
||||
enum Enum {
|
||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||
#[serde(skip_serializing)]
|
||||
Unit,
|
||||
}
|
||||
|
||||
fn serialize_some_unit_variant<S>(_: S) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
@@ -811,6 +811,74 @@ fn test_serialize_with_enum() {
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize)]
|
||||
enum SerializeWithVariant {
|
||||
#[serde(serialize_with="serialize_unit_variant_as_i8")]
|
||||
Unit,
|
||||
|
||||
#[serde(serialize_with="SerializeWith::serialize_with")]
|
||||
Newtype(i32),
|
||||
|
||||
#[serde(serialize_with="serialize_some_other_variant")]
|
||||
Tuple(String, u8),
|
||||
|
||||
#[serde(serialize_with="serialize_some_other_variant")]
|
||||
Struct {
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
}
|
||||
|
||||
fn serialize_unit_variant_as_i8<S>(serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
serializer.serialize_i8(0)
|
||||
}
|
||||
|
||||
fn serialize_some_other_variant<S>(f1: &String,
|
||||
f2: &u8,
|
||||
serializer: S)
|
||||
-> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(format!("{};{:?}", f1, f2).as_str())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_with_variant() {
|
||||
assert_ser_tokens(
|
||||
&SerializeWithVariant::Unit,
|
||||
&[
|
||||
Token::NewtypeVariant { name: "SerializeWithVariant", variant: "Unit" },
|
||||
Token::I8(0),
|
||||
],
|
||||
);
|
||||
|
||||
assert_ser_tokens(
|
||||
&SerializeWithVariant::Newtype(123),
|
||||
&[
|
||||
Token::NewtypeVariant { name: "SerializeWithVariant", variant: "Newtype" },
|
||||
Token::Bool(true),
|
||||
],
|
||||
);
|
||||
|
||||
assert_ser_tokens(
|
||||
&SerializeWithVariant::Tuple("hello".into(), 0),
|
||||
&[
|
||||
Token::NewtypeVariant { name: "SerializeWithVariant", variant: "Tuple" },
|
||||
Token::Str("hello;0"),
|
||||
],
|
||||
);
|
||||
|
||||
assert_ser_tokens(
|
||||
&SerializeWithVariant::Struct { f1: "world".into(), f2: 1 },
|
||||
&[
|
||||
Token::NewtypeVariant { name: "SerializeWithVariant", variant: "Struct" },
|
||||
Token::Str("world;1"),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
struct DeserializeWithStruct<B>
|
||||
where
|
||||
|
||||
@@ -373,6 +373,124 @@ fn test_gen() {
|
||||
#[serde(with = "vis::SDef")]
|
||||
s: vis::S,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
enum ExternallyTaggedVariantWith {
|
||||
#[allow(dead_code)]
|
||||
Normal { f1: String },
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
Newtype(X),
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Tuple(String, u8),
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Struct {
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
|
||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||
#[allow(dead_code)]
|
||||
Unit,
|
||||
}
|
||||
assert_ser::<ExternallyTaggedVariantWith>();
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(tag = "t")]
|
||||
enum InternallyTaggedVariantWith {
|
||||
#[allow(dead_code)]
|
||||
Normal { f1: String },
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
Newtype(X),
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Struct {
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
|
||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||
#[allow(dead_code)]
|
||||
Unit,
|
||||
}
|
||||
assert_ser::<InternallyTaggedVariantWith>();
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum AdjacentlyTaggedVariantWith {
|
||||
#[allow(dead_code)]
|
||||
Normal { f1: String },
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
Newtype(X),
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Tuple(String, u8),
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Struct {
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
|
||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||
#[allow(dead_code)]
|
||||
Unit,
|
||||
}
|
||||
assert_ser::<AdjacentlyTaggedVariantWith>();
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(untagged)]
|
||||
enum UntaggedVariantWith {
|
||||
#[allow(dead_code)]
|
||||
Normal { f1: String },
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
Newtype(X),
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Tuple(String, u8),
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Struct {
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
|
||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||
#[allow(dead_code)]
|
||||
Unit,
|
||||
}
|
||||
assert_ser::<UntaggedVariantWith>();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -414,3 +532,29 @@ impl DeserializeWith for X {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize_some_unit_variant<S>(_: S) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn deserialize_some_unit_variant<'de, D>(_: D) -> StdResult<(), D::Error>
|
||||
where D: Deserializer<'de>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn serialize_some_other_variant<S>(_: &String, _: &u8, _: S) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error>
|
||||
where D: Deserializer<'de>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn is_zero(n: &u8) -> bool { *n == 0 }
|
||||
|
||||
Reference in New Issue
Block a user