fix: unmarshal LB top recordings from snake_case wire format, cap at 10
The ListenBrainz popularity API returns snake_case JSON fields (recording_name, artist_name, total_listen_count, recording_mbid) but LBTopRecording used camelCase JSON tags for Wails serialization. All fields silently deserialized as zero values — empty strings and zero counts — producing ~8000 blank rows in the top tracks section. Fix: add lbTopRecordingWire with snake_case tags for API unmarshal, convert to LBTopRecording (camelCase) for Wails. Cap results at 10 to avoid rendering thousands of rows for prolific artists.
This commit is contained in:
@@ -68,12 +68,25 @@ func (c *ListenBrainzClient) TopRecordingsForArtist(
|
|||||||
return nil, fmt.Errorf("listenbrainz top recordings: %w", err)
|
return nil, fmt.Errorf("listenbrainz top recordings: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The API returns an array directly.
|
// The API returns snake_case JSON — unmarshal into wire type,
|
||||||
var out []LBTopRecording
|
// then convert to the camelCase Wails type.
|
||||||
if err := json.Unmarshal(body, &out); err != nil {
|
var wire []lbTopRecordingWire
|
||||||
|
if err := json.Unmarshal(body, &wire); err != nil {
|
||||||
return nil, fmt.Errorf("listenbrainz top recordings unmarshal: %w", err)
|
return nil, fmt.Errorf("listenbrainz top recordings unmarshal: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxTopRecordings = 10
|
||||||
|
|
||||||
|
limit := len(wire)
|
||||||
|
if limit > maxTopRecordings {
|
||||||
|
limit = maxTopRecordings
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make([]LBTopRecording, limit)
|
||||||
|
for i := range limit {
|
||||||
|
out[i] = wire[i].toPublic()
|
||||||
|
}
|
||||||
|
|
||||||
c.cacheJSON(cacheKey, out, cacheTTLSearch, artistMBID, "artist")
|
c.cacheJSON(cacheKey, out, cacheTTLSearch, artistMBID, "artist")
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ type MBTrack struct {
|
|||||||
|
|
||||||
// LBTopRecording represents a popular recording from the
|
// LBTopRecording represents a popular recording from the
|
||||||
// ListenBrainz popularity API.
|
// ListenBrainz popularity API.
|
||||||
|
//
|
||||||
|
// JSON tags use camelCase for Wails→frontend serialization.
|
||||||
|
// The API response uses snake_case, so we unmarshal into
|
||||||
|
// lbTopRecordingWire first, then convert.
|
||||||
type LBTopRecording struct {
|
type LBTopRecording struct {
|
||||||
RecordingMBID string `json:"recordingMbid"`
|
RecordingMBID string `json:"recordingMbid"`
|
||||||
ArtistName string `json:"artistName"`
|
ArtistName string `json:"artistName"`
|
||||||
@@ -75,6 +79,25 @@ type LBTopRecording struct {
|
|||||||
TotalListenCount int `json:"totalListenCount"`
|
TotalListenCount int `json:"totalListenCount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lbTopRecordingWire matches the ListenBrainz API's snake_case
|
||||||
|
// JSON response for the popularity/top-recordings-for-artist
|
||||||
|
// endpoint.
|
||||||
|
type lbTopRecordingWire struct {
|
||||||
|
RecordingMBID string `json:"recording_mbid"`
|
||||||
|
ArtistName string `json:"artist_name"`
|
||||||
|
RecordingName string `json:"recording_name"`
|
||||||
|
TotalListenCount int `json:"total_listen_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w lbTopRecordingWire) toPublic() LBTopRecording {
|
||||||
|
return LBTopRecording{
|
||||||
|
RecordingMBID: w.RecordingMBID,
|
||||||
|
ArtistName: w.ArtistName,
|
||||||
|
TrackName: w.RecordingName,
|
||||||
|
TotalListenCount: w.TotalListenCount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LBSimilarArtist represents a similar artist from the
|
// LBSimilarArtist represents a similar artist from the
|
||||||
// ListenBrainz labs API.
|
// ListenBrainz labs API.
|
||||||
type LBSimilarArtist struct {
|
type LBSimilarArtist struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user