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)
|
||||
}
|
||||
|
||||
// The API returns an array directly.
|
||||
var out []LBTopRecording
|
||||
if err := json.Unmarshal(body, &out); err != nil {
|
||||
// The API returns snake_case JSON — unmarshal into wire type,
|
||||
// then convert to the camelCase Wails type.
|
||||
var wire []lbTopRecordingWire
|
||||
if err := json.Unmarshal(body, &wire); err != nil {
|
||||
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")
|
||||
|
||||
return out, nil
|
||||
|
||||
@@ -68,6 +68,10 @@ type MBTrack struct {
|
||||
|
||||
// LBTopRecording represents a popular recording from the
|
||||
// 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 {
|
||||
RecordingMBID string `json:"recordingMbid"`
|
||||
ArtistName string `json:"artistName"`
|
||||
@@ -75,6 +79,25 @@ type LBTopRecording struct {
|
||||
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
|
||||
// ListenBrainz labs API.
|
||||
type LBSimilarArtist struct {
|
||||
|
||||
Reference in New Issue
Block a user