fix(album): use dedicated tolerant AlbumAward struct instead of mutating PageArtistAward

Previous attempt loosened PageArtistAward (id u64 -> Option<u64>,
awarded_at custom deserializer) to accept /album/get's inconsistent
award shape. That rippled into /artist/page consumers, which the user
rightly called out ('no eliminar lo que ya funcionaba, adaptar pues').

Restores PageArtistAward to its original shape (id: u64, name: String,
awarded_at: Option<String>) and introduces a parallel AlbumAward type
used only on DiscoverAlbum and Album. AlbumAward tolerates missing id,
accepts awarded_at as int or string, and never fails deserialization
of the parent payload. /artist/page keeps its strict contract.

cc
This commit is contained in:
vicrodh committed 2026-04-14 12:30:18 -06:00
1 parent fe3213ece5
commit ee2f413ec1
3 files changed
+37 -17

No files matched your search

+15 -7
View File
@@ -232,7 +232,7 @@ pub struct Album {
pub description: Option<String>,
/// Editorial awards attached to the album.
#[serde(default)]
pub awards: Option<Vec<PageArtistAward>>,
pub awards: Option<Vec<AlbumAward>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -965,13 +965,22 @@ pub struct PageArtistRights {
pub struct PageArtistAward {
pub id: u64,
pub name: String,
/// Qobuz returns this either as "YYYY-MM-DD" or a Unix timestamp
/// integer depending on the endpoint — accept both.
#[serde(default, deserialize_with = "deserialize_awarded_at")]
pub awarded_at: Option<String>,
}
fn deserialize_awarded_at<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
/// Tolerant award struct used in Album responses where Qobuz is
/// inconsistent about optional id and awarded_at types.
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AlbumAward {
#[serde(default)]
pub id: Option<u64>,
#[serde(default)]
pub name: String,
#[serde(default, deserialize_with = "deserialize_album_awarded_at")]
pub awarded_at: Option<String>,
}
fn deserialize_album_awarded_at<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: serde::Deserializer<'de>,
{
@@ -979,8 +988,7 @@ where
Ok(match value {
Some(serde_json::Value::String(s)) => Some(s),
Some(serde_json::Value::Number(n)) => Some(n.to_string()),
Some(serde_json::Value::Null) | None => None,
Some(_) => None,
_ => None,
})
}