midiserde 0.1.1

When mini isn't enough and serde is too much
Documentation
//! Tests for `#[mini(skip_serializing_if = "path")]`.
//!
//! Run: `cargo test -p midiserde skip_serializing_if`

use midiserde::{from_value, json, to_value, Deserialize, Serialize};

#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct WithOptionSkip {
    name: String,
    #[mini(skip_serializing_if = "Option::is_none")]
    friend: Option<String>,
}

#[test]
fn option_is_none_omits_when_none() {
    let v = WithOptionSkip {
        name: "alice".into(),
        friend: None,
    };
    let j = json::to_string(&v);
    assert!(j.contains(r#""name":"alice""#));
    assert!(!j.contains("friend"));
}

#[test]
fn option_is_none_includes_when_some() {
    let v = WithOptionSkip {
        name: "bob".into(),
        friend: Some("charlie".into()),
    };
    let j = json::to_string(&v);
    assert!(j.contains(r#""name":"bob""#));
    assert!(j.contains(r#""friend":"charlie""#));
}

#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct WithVecSkip {
    name: String,
    #[mini(skip_serializing_if = "Vec::is_empty")]
    tags: Vec<String>,
}

#[test]
fn vec_is_empty_omits_when_empty() {
    let v = WithVecSkip {
        name: "x".into(),
        tags: vec![],
    };
    let j = json::to_string(&v);
    assert!(!j.contains("tags"));
}

#[test]
fn vec_is_empty_includes_when_non_empty() {
    let v = WithVecSkip {
        name: "x".into(),
        tags: vec!["a".into(), "b".into()],
    };
    let j = json::to_string(&v);
    assert!(j.contains("tags"));
}

// Custom predicate (must be in scope)
fn is_empty_str(s: &str) -> bool {
    s.is_empty()
}

#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct WithCustomSkip {
    name: String,
    #[mini(skip_serializing_if = "crate::is_empty_str")]
    nickname: String,
}

#[test]
fn custom_skip_omits_when_empty() {
    let v = WithCustomSkip {
        name: "alice".into(),
        nickname: "".into(),
    };
    let j = json::to_string(&v);
    assert!(!j.contains("nickname"));
}

#[test]
fn custom_skip_includes_when_non_empty() {
    let v = WithCustomSkip {
        name: "alice".into(),
        nickname: "ali".into(),
    };
    let j = json::to_string(&v);
    assert!(j.contains(r#""nickname":"ali""#));
}

#[test]
fn roundtrip_option_skip() {
    let original = WithOptionSkip {
        name: "roundtrip".into(),
        friend: Some("pal".into()),
    };
    let value = to_value(&original);
    let restored: WithOptionSkip = from_value(&value).unwrap();
    assert_eq!(original, restored);
}

#[test]
fn roundtrip_option_skip_none() {
    let original = WithOptionSkip {
        name: "solo".into(),
        friend: None,
    };
    let value = to_value(&original);
    let restored: WithOptionSkip = from_value(&value).unwrap();
    assert_eq!(original, restored);
}