serde-ignored-fields 0.1.1

preserve ignored fields with serde
Documentation
#![cfg(feature = "toml")]

use assert2::{assert, let_assert};
use indoc::indoc;
use serde_ignored_fields::PreserveIgnoredFields;

#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
struct Person {
	name: String,
	hobby: String,
}

fn json<T: serde::de::DeserializeOwned>(
	data: &str,
) -> Result<PreserveIgnoredFields<T, serde_json::Map<String, serde_json::Value>>, serde_json::Error> {
	serde::Deserialize::deserialize(&mut serde_json::Deserializer::from_str(data))
}

macro_rules! json {
	({ $($name:ident: $value:tt),* $(,)? }) => {
		{
			#[allow(unused_mut)]
			let mut map = serde_json::Map::new();
			$(map.insert(String::from(::core::stringify!($name)), json!($value).into());)*
			map
		}
	};
	([ $($value:tt),* $(,)? ]) => {
		{
			#[allow(unused_mut)]
			let mut vec = Vec::<serde_json::Value>::new();
			$(vec.push(json!($value).into());)*
			vec
		}
	};
	($($name:ident: $value:tt),* $(,)?) => {
		json!({ $($name: $value,)* })
	};
	($value:expr) => {
		serde_json::Value::from($value)
	};
}

#[test]
fn deserialize_extra() {
	let_assert!(Ok(deserialized) = json::<Person>(indoc!(r#"
	{
	  "name": "Zohan",
	  "hobby": "hair-dressing",
	  "glasses": false,
	  "friends": [
	    {"name": "Scrappy", "species": "dog"},
	    {"name": "Coco", "species": "dog"}
	  ]
	}
	"#)));

	assert!(deserialized.value == Person {
		name: "Zohan".into(),
		hobby: "hair-dressing".into(),
	});

	assert!(deserialized.ignored_fields == json! {
		glasses: false,
		friends: [
			{ name: "Scrappy", species: "dog" },
			{ name: "Coco", species: "dog" },
		],
	});
}

#[test]
fn serialize_extra() {
	let zohan = PreserveIgnoredFields {
		value: Person {
			name: "Zohan".to_string(),
			hobby: "hair-dressing".to_string(),
		},
		ignored_fields: json! {
			glasses: false,
			friends: [
				{ name: "Scrappy", species: "dog" },
				{ name: "Coco", species: "dog" },
			],
		},
	};

	let_assert!(Ok(serialized) = ::serde_json::to_string_pretty(&zohan));
	assert!(serialized == indoc!(r#"
	{
	  "name": "Zohan",
	  "hobby": "hair-dressing",
	  "glasses": false,
	  "friends": [
	    {
	      "name": "Scrappy",
	      "species": "dog"
	    },
	    {
	      "name": "Coco",
	      "species": "dog"
	    }
	  ]
	}
	"#).trim())
}