use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(bound(deserialize = "T: serde::de::DeserializeOwned"))]
pub struct Page<T> {
pub offset: i64,
pub limit: i32,
pub count: i32,
pub total_count: i64,
#[serde(deserialize_with = "lenient_items")]
pub data: Vec<T>,
}
fn lenient_items<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
where
D: serde::Deserializer<'de>,
T: serde::de::DeserializeOwned,
{
let raw = Vec::<Value>::deserialize(deserializer)?;
Ok(raw
.into_iter()
.filter_map(|item| match serde_json::from_value::<T>(item) {
Ok(parsed) => Some(parsed),
Err(error) => {
tracing::warn!(
item_type = std::any::type_name::<T>(),
category = ?error.classify(),
"skipping list item that failed to parse"
);
None
}
})
.collect())
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SiteResponse {
pub id: Uuid,
pub name: String,
pub internal_reference: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplicationInfoResponse {
#[serde(flatten)]
pub fields: HashMap<String, Value>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ErrorResponse {
pub message: Option<String>,
#[serde(flatten)]
pub extra: HashMap<String, Value>,
}