use {
serde::{Deserialize, Deserializer, Serialize, de::Error},
serde_json::{
Value,
Value::{Null, Object},
from_value,
},
};
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct AudioInfo {
pub bit_depth: Option<i32>,
pub sampling_rate: Option<f64>,
pub channels: Option<i32>,
pub codec: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct Biography {
pub text: Option<String>,
pub summary: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct Genre {
pub id: Option<i32>,
pub name: Option<String>,
pub slug: Option<String>,
pub color: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
pub struct Image {
pub small: Option<String>,
pub thumbnail: Option<String>,
pub medium: Option<String>,
pub large: Option<String>,
#[serde(rename = "extralarge")]
pub extra_large: Option<String>,
pub mega: Option<String>,
pub back: Option<String>,
pub url: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct Label {
pub id: Option<i32>,
pub name: Option<String>,
pub slug: Option<String>,
}
pub fn deserialize_flexible_name<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
let value = deserialize_optional_value(deserializer)?;
if let Some(s) = value.as_ref().and_then(|v| v.as_str()) {
return Ok(Some(s.to_string()));
}
match value {
None | Some(Null) => Ok(None),
Some(Object(map)) => map
.get("display")
.and_then(Value::as_str)
.map(|s| Some(s.to_string()))
.ok_or_else(|| Error::custom("object missing 'display' field")),
Some(v) => Ok(map_value_to_string(Some(v))),
}
}
pub fn deserialize_flexible_string_id<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
let value = deserialize_optional_value(deserializer)?;
Ok(map_value_to_string(value))
}
fn deserialize_optional_value<'de, D>(deserializer: D) -> Result<Option<Value>, D::Error>
where
D: Deserializer<'de>,
{
Option::<Value>::deserialize(deserializer)
}
pub fn deserialize_picture<'de, D>(deserializer: D) -> Result<Option<Image>, D::Error>
where
D: Deserializer<'de>,
{
let value = deserialize_optional_value(deserializer)?;
match value {
None | Some(Null) => Ok(None),
Some(v) if v.is_string() => Ok(None),
Some(v) => from_value(v).map_err(Error::custom),
}
}
fn map_value_to_string(value: Option<Value>) -> Option<String> {
match value {
None | Some(Null) => None,
Some(v) => Some(
v.as_str()
.map_or_else(|| v.to_string(), ToString::to_string),
),
}
}