Fix ID fields to accept both JSON strings and numbers
The Yandex Music API returns IDs as both JSON strings and numbers depending on the endpoint. Added JSONID custom type in internal/models/base.go that implements json.Unmarshaler to accept both formats and store as string. Changed ID fields from string to JSONID: - Track.ID, Major.ID, TrackLyricsInfo.ID (track.go) - Album.ID, TrailerInfo.TrackID, TrailerInfo.AlbumID (album.go) Updated example to convert JSONID to string when passing to client methods. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
1 parent
0456ca0665
commit
5535d2a941
4 files changed
+49
-20
No files matched your search
@@ -57,7 +57,7 @@ func main() {
|
|||||||
// Example: Get track by ID (if we have results)
|
// Example: Get track by ID (if we have results)
|
||||||
if len(tracks) > 0 {
|
if len(tracks) > 0 {
|
||||||
fmt.Println("\n--- Getting track details ---")
|
fmt.Println("\n--- Getting track details ---")
|
||||||
track, err := client.GetTrack(ctx, tracks[0].ID)
|
track, err := client.GetTrack(ctx, string(tracks[0].ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Get track failed: %v", err)
|
log.Printf("Get track failed: %v", err)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+16
-16
@@ -8,20 +8,20 @@ import (
|
|||||||
// Album represents a full album from the Yandex Music API.
|
// Album represents a full album from the Yandex Music API.
|
||||||
type Album struct {
|
type Album struct {
|
||||||
BaseModel
|
BaseModel
|
||||||
ID string `json:"id"`
|
ID JSONID `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
CoverURI string `json:"cover_uri"`
|
CoverURI string `json:"cover_uri"`
|
||||||
Genre string `json:"genre"`
|
Genre string `json:"genre"`
|
||||||
Year int `json:"year"`
|
Year int `json:"year"`
|
||||||
TrackCount int `json:"track_count"`
|
TrackCount int `json:"track_count"`
|
||||||
Available bool `json:"available"`
|
Available bool `json:"available"`
|
||||||
ReleaseDate string `json:"release_date"`
|
ReleaseDate string `json:"release_date"`
|
||||||
Artists []Artist `json:"artists"`
|
Artists []Artist `json:"artists"`
|
||||||
Labels []Label `json:"labels"`
|
Labels []Label `json:"labels"`
|
||||||
Volumes [][]Track `json:"volumes"`
|
Volumes [][]Track `json:"volumes"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Meta *AlbumMeta `json:"meta"`
|
Meta *AlbumMeta `json:"meta"`
|
||||||
Best *Best `json:"best"`
|
Best *Best `json:"best"`
|
||||||
// Additional fields
|
// Additional fields
|
||||||
Region string `json:"region"`
|
Region string `json:"region"`
|
||||||
AvailableForPremiumUsers bool `json:"available_for_premium_users"`
|
AvailableForPremiumUsers bool `json:"available_for_premium_users"`
|
||||||
@@ -226,8 +226,8 @@ type Best struct {
|
|||||||
type TrailerInfo struct {
|
type TrailerInfo struct {
|
||||||
BaseModel
|
BaseModel
|
||||||
PreviewURI string `json:"preview_uri"`
|
PreviewURI string `json:"preview_uri"`
|
||||||
TrackID string `json:"track_id"`
|
TrackID JSONID `json:"track_id"`
|
||||||
AlbumID string `json:"album_id"`
|
AlbumID JSONID `json:"album_id"`
|
||||||
Duration int `json:"duration"`
|
Duration int `json:"duration"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
|
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
|
||||||
)
|
)
|
||||||
@@ -81,3 +83,30 @@ func (b *BaseModel) SetClient(c ClientInterface) {
|
|||||||
func (b *BaseModel) GetClient() ClientInterface {
|
func (b *BaseModel) GetClient() ClientInterface {
|
||||||
return b.Client
|
return b.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSONID is an ID that can be represented as either a JSON string or a JSON number.
|
||||||
|
// The Yandex Music API sometimes returns IDs as numbers (e.g., 12345) and sometimes
|
||||||
|
// as strings (e.g., "12345"). JSONID accepts both and stores the value as a string.
|
||||||
|
type JSONID string
|
||||||
|
|
||||||
|
// UnmarshalJSON implements json.Unmarshaler, accepting both JSON strings and numbers.
|
||||||
|
func (id *JSONID) UnmarshalJSON(data []byte) error {
|
||||||
|
// Try string first
|
||||||
|
var s string
|
||||||
|
if err := json.Unmarshal(data, &s); err == nil {
|
||||||
|
*id = JSONID(s)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Try number (float64 is the default JSON number decoding)
|
||||||
|
var f float64
|
||||||
|
if err := json.Unmarshal(data, &f); err != nil {
|
||||||
|
return fmt.Errorf("cannot unmarshal %v into JSONID: %w", string(data), err)
|
||||||
|
}
|
||||||
|
*id = JSONID(strconv.FormatFloat(f, 'f', -1, 64))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the ID as a Go string.
|
||||||
|
func (id JSONID) String() string {
|
||||||
|
return string(id)
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
// Track represents a full track from the Yandex Music API.
|
// Track represents a full track from the Yandex Music API.
|
||||||
type Track struct {
|
type Track struct {
|
||||||
BaseModel
|
BaseModel
|
||||||
ID string `json:"id"`
|
ID JSONID `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
DurationMs int `json:"duration_ms"`
|
DurationMs int `json:"duration_ms"`
|
||||||
StorageID string `json:"storage_id"`
|
StorageID string `json:"storage_id"`
|
||||||
@@ -149,14 +149,14 @@ func (t *Track) GetDownloadInfo(quality string) *DownloadInfo {
|
|||||||
|
|
||||||
// Major represents major label info for a track.
|
// Major represents major label info for a track.
|
||||||
type Major struct {
|
type Major struct {
|
||||||
ID string `json:"id"`
|
ID JSONID `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackLyricsInfo represents minimal lyrics info for a track.
|
// TrackLyricsInfo represents minimal lyrics info for a track.
|
||||||
type TrackLyricsInfo struct {
|
type TrackLyricsInfo struct {
|
||||||
ID string `json:"id"`
|
ID JSONID `json:"id"`
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
Major *Major `json:"major"`
|
Major *Major `json:"major"`
|
||||||
Available bool `json:"available"`
|
Available bool `json:"available"`
|
||||||
|
|||||||
Reference in new issue
Block a user