#![doc = include_str!("../README.md")]
#[cfg(test)]
extern crate self as json_serde;
use serde_core::{
Deserialize, Deserializer, Serializer,
de::Error,
ser::{Impossible, SerializeSeq},
};
pub fn deserialize_some<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de>,
{
T::deserialize(deserializer).map(Some)
}
pub struct FlattenedSequenceSerializer<'a, S>(&'a mut S);
impl<'a, S> FlattenedSequenceSerializer<'a, S>
where
S: serde_core::ser::SerializeSeq,
{
pub fn new(seq_serializer: &'a mut S) -> Self {
Self(seq_serializer)
}
fn wrong_type_error<T>() -> Result<T, S::Error> {
Err(serde_core::ser::Error::custom(
"FlattenedSequenceSerializer only supports sequence values",
))
}
}
impl<'a, S> Serializer for FlattenedSequenceSerializer<'a, S>
where
S: serde_core::ser::SerializeSeq,
{
type Ok = ();
type Error = S::Error;
type SerializeSeq = Self;
type SerializeTuple = Impossible<Self::Ok, Self::Error>;
type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
type SerializeMap = serde_core::ser::Impossible<Self::Ok, Self::Error>;
type SerializeStruct = serde_core::ser::Impossible<Self::Ok, Self::Error>;
type SerializeStructVariant = serde_core::ser::Impossible<Self::Ok, Self::Error>;
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Ok(self)
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
Self::wrong_type_error()
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Self::wrong_type_error()
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Self::wrong_type_error()
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Err(serde_core::ser::Error::custom(
"FlattenedSequenceSerializer does not support maps",
))
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Err(serde_core::ser::Error::custom(
"FlattenedSequenceSerializer does not support structs",
))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(serde_core::ser::Error::custom(
"FlattenedSequenceSerializer does not support struct variants",
))
}
fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_str(self, _v: &str) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_some<T>(self, _value: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + serde_core::Serialize,
{
Self::wrong_type_error()
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Self::wrong_type_error()
}
fn serialize_newtype_struct<T>(
self,
_name: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + serde_core::Serialize,
{
Self::wrong_type_error()
}
fn serialize_newtype_variant<T>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + serde_core::Serialize,
{
Self::wrong_type_error()
}
}
impl<'a, S> SerializeSeq for FlattenedSequenceSerializer<'a, S>
where
S: serde_core::ser::SerializeSeq,
{
type Ok = ();
type Error = S::Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: ?Sized + serde_core::Serialize,
{
self.0.serialize_element(value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}
pub struct FlattenedSequenceDeserializer<'a, S>(&'a mut S);
impl<'a, S> FlattenedSequenceDeserializer<'a, S> {
pub fn new(seq_access: &'a mut S) -> Self {
Self(seq_access)
}
}
impl<'de, 'a, S> Deserializer<'de> for FlattenedSequenceDeserializer<'a, S>
where
S: serde_core::de::SeqAccess<'de>,
{
type Error = S::Error;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, S::Error>
where
V: serde_core::de::Visitor<'de>,
{
Err(S::Error::custom("type must expect a sequence"))
}
serde_core::forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct tuple
tuple_struct map struct enum identifier ignored_any
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde_core::de::Visitor<'de>,
{
visitor.visit_seq(self.0)
}
}
pub fn always<T>(_: &T) -> bool {
true
}
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Absent;
impl serde_core::Serialize for Absent {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde_core::ser::Error;
Err(S::Error::custom(
"field must be annotated with `skip_serializing` (or \
`skip_serializing_if = \"json_serde::always\"`)",
))
}
}
impl<'de> Deserialize<'de> for Absent {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde_core::de::Error;
let _ = serde_core::de::IgnoredAny::deserialize(deserializer)?;
Err(D::Error::custom("field must be absent"))
}
}
#[cfg(feature = "schemars08")]
impl schemars08::JsonSchema for Absent {
fn schema_name() -> String {
"Absent".to_string()
}
fn json_schema(_: &mut schemars08::r#gen::SchemaGenerator) -> schemars08::schema::Schema {
schemars08::schema::Schema::Bool(false)
}
fn is_referenceable() -> bool {
false
}
}
#[cfg(feature = "schemars1")]
impl schemars1::JsonSchema for Absent {
fn schema_name() -> std::borrow::Cow<'static, str> {
std::borrow::Cow::Borrowed("Absent")
}
fn json_schema(_: &mut schemars1::SchemaGenerator) -> schemars1::Schema {
schemars1::Schema::from(false)
}
fn inline_schema() -> bool {
true
}
}
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize, ser::SerializeSeq};
use crate::{Absent, FlattenedSequenceDeserializer, FlattenedSequenceSerializer};
#[test]
fn test_deserialize_some() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Test {
#[serde(
default,
deserialize_with = "::json_serde::deserialize_some",
skip_serializing_if = "Option::is_none"
)]
field: Option<String>,
}
let de = serde_json::from_str::<Test>("{}").unwrap();
assert_eq!(de.field, None);
assert!(serde_json::from_str::<Test>(r#"{ "field": null }"#).is_err());
let de = serde_json::from_str::<Test>(r#"{ "field": "value" }"#).unwrap();
assert_eq!(de.field, Some("value".to_string()));
}
#[test]
fn test_deserialize_some_double_option() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Test {
#[serde(
default,
deserialize_with = "::json_serde::deserialize_some",
skip_serializing_if = "Option::is_none"
)]
field: Option<Option<String>>,
}
let de = serde_json::from_str::<Test>("{}").unwrap();
assert_eq!(de.field, None);
let de = serde_json::from_str::<Test>(r#"{ "field": null }"#).unwrap();
assert_eq!(de.field, Some(None));
let de = serde_json::from_str::<Test>(r#"{ "field": "value" }"#).unwrap();
assert_eq!(de.field, Some(Some("value".to_string())));
}
#[test]
fn flatten_tuple_vec() {
#[derive(Debug, Eq, PartialEq)]
struct TestType(u32, String, Vec<u32>);
impl Serialize for TestType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut seq = serializer.serialize_seq(None)?;
seq.serialize_element(&self.0)?;
seq.serialize_element(&self.1)?;
self.2
.serialize(FlattenedSequenceSerializer::new(&mut seq))?;
seq.end()
}
}
impl<'de> Deserialize<'de> for TestType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct Visitor;
impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = TestType;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a flattened tuple vec")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let v_0 = seq.next_element()?.ok_or_else(|| {
serde::de::Error::invalid_length(0, &"a tuple of size 2")
})?;
let v_1 = seq.next_element()?.ok_or_else(|| {
serde::de::Error::invalid_length(1, &"a tuple of size 2")
})?;
let rest =
Deserialize::deserialize(FlattenedSequenceDeserializer::new(&mut seq))?;
Ok(TestType(v_0, v_1, rest))
}
}
deserializer.deserialize_seq(Visitor)
}
}
let value = TestType(42, "Hello".to_string(), vec![1, 2, 3]);
let serialized = serde_json::to_string(&value).unwrap();
assert_eq!(serialized, "[42,\"Hello\",1,2,3]");
let de_value = serde_json::from_str::<TestType>(&serialized).unwrap();
assert_eq!(value, de_value);
let value = TestType(7, "World".to_string(), vec![]);
let serialized = serde_json::to_string(&value).unwrap();
assert_eq!(serialized, "[7,\"World\"]");
let de_value = serde_json::from_str::<TestType>(&serialized).unwrap();
assert_eq!(value, de_value);
let input = "[1, \"Two\", \"Three\", 4, 5, 6]";
let de_result = serde_json::from_str::<TestType>(input);
assert!(de_result.is_err());
let input = "[100]";
let de_result = serde_json::from_str::<TestType>(input);
let e = de_result.unwrap_err().to_string();
assert!(
e.starts_with("invalid length 1, expected a tuple of size 2"),
"{e}",
);
let input = "[1, \"Two\", \"Three\"]";
let de_result = serde_json::from_str::<TestType>(input);
let e = de_result.unwrap_err().to_string();
assert!(e.starts_with("invalid type"), "{e}",);
}
#[test]
fn test_absent() {
#[derive(Serialize, Deserialize)]
struct Test {
#[serde(default, skip_serializing)]
absent: Absent,
}
let test = Test { absent: Absent };
assert_eq!(serde_json::to_string(&test).unwrap(), "{}");
let de = serde_json::from_str::<Test>("{}").unwrap();
let Absent = de.absent;
assert!(serde_json::from_str::<Test>(r#"{ "absent": null }"#).is_err());
}
#[cfg(feature = "schemars08")]
#[test]
fn test_absent_schema() {
#[derive(Serialize, Deserialize, schemars08::JsonSchema)]
#[schemars(crate = "schemars08")]
struct Test {
#[serde(skip_serializing_if = "crate::always")]
#[serde(default)]
absent: Absent,
}
let test = Test { absent: Absent };
assert_eq!(serde_json::to_string(&test).unwrap(), "{}");
assert!(serde_json::from_str::<Test>(r#"{ "absent": null }"#).is_err());
let schema = schemars08::schema_for!(Test);
let expected = serde_json::json!({
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Test",
"type": "object",
"properties": {
"absent": false
}
});
assert_eq!(serde_json::to_value(&schema).unwrap(), expected);
}
#[cfg(feature = "schemars1")]
#[test]
fn test_absent_schema_v1() {
#[derive(Serialize, Deserialize, schemars1::JsonSchema)]
#[schemars(crate = "schemars1")]
struct Test {
#[serde(default, skip_serializing)]
absent: Absent,
}
let test = Test { absent: Absent };
assert_eq!(serde_json::to_string(&test).unwrap(), "{}");
let de = serde_json::from_str::<Test>("{}").unwrap();
let Absent = de.absent;
assert!(serde_json::from_str::<Test>(r#"{ "absent": null }"#).is_err());
let schema = schemars1::schema_for!(Test);
let expected = serde_json::json!({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Test",
"type": "object",
"properties": {
"absent": {
"not": {},
"writeOnly": true
}
}
});
assert_eq!(serde_json::to_value(&schema).unwrap(), expected);
}
}