matomo-rs 0.1.1

Async client for the Matomo Reporting API, focused on data export and migration
Documentation
use serde::de::DeserializeOwned;
use serde::{Deserialize, Deserializer};
use serde_json::Value;

/// Matomo encodes "no items" as integer `0` (and occasionally `null`, `[]` or
/// `{}`) but a populated list as an array of objects. Map all of the empty
/// forms to an empty `Vec`, and otherwise deserialize the array.
///
/// One reusable deserializer; do not scatter untagged enums for this.
pub fn empty_or_vec<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
where
    D: Deserializer<'de>,
    T: DeserializeOwned,
{
    let value = Value::deserialize(deserializer)?;
    // Arrays and non-empty objects hold items; `0`, `null`, `[]`, `{}` and any
    // other scalar Matomo uses for "none" map to empty.
    let has_items = matches!(&value, Value::Array(_))
        || matches!(&value, Value::Object(map) if !map.is_empty());
    if has_items {
        serde_json::from_value(value).map_err(serde::de::Error::custom)
    } else {
        Ok(Vec::new())
    }
}