use serde::{Deserialize, Serialize};
use super::{Link, Meta};
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct ErrorSource {
#[serde(skip_serializing_if = "Option::is_none")]
pub pointer: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parameter: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub header: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct ErrorLinks {
#[serde(skip_serializing_if = "Option::is_none")]
pub about: Option<Link>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub type_: Option<Link>,
}
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct ApiError {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub links: Option<ErrorLinks>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<ErrorSource>,
#[serde(skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_api_error_round_trip() {
let json = r#"{"status":"404","title":"Not Found","detail":"Article 99 not found"}"#;
let err: ApiError = serde_json::from_str(json).unwrap();
assert_eq!(err.status.as_deref(), Some("404"));
assert_eq!(err.title.as_deref(), Some("Not Found"));
assert_eq!(serde_json::to_string(&err).unwrap(), json);
}
#[test]
fn test_api_error_with_source_pointer() {
let json = r#"{"status":"422","source":{"pointer":"/data/attributes/title"}}"#;
let err: ApiError = serde_json::from_str(json).unwrap();
assert_eq!(
err.source.as_ref().unwrap().pointer.as_deref(),
Some("/data/attributes/title")
);
}
#[test]
fn test_api_error_with_type_link() {
let json = r#"{"status":"422","links":{"type":"http://example.com/errors/invalid"}}"#;
let err: ApiError = serde_json::from_str(json).unwrap();
assert!(err.links.as_ref().unwrap().type_.is_some());
}
}