Fix marshaling for genres.

This commit is contained in:
Caio Cotts 2023-11-21 20:09:12 -05:00 committed by Deluan Quintão
parent 5d1493e845
commit bb7186ce2f
10 changed files with 233 additions and 83 deletions

View File

@ -0,0 +1,55 @@
{
"status": "ok",
"version": "1.8.0",
"type": "navidrome",
"serverVersion": "v0.0.0",
"openSubsonic": true,
"album": {
"id": "1",
"name": "album",
"artist": "artist",
"userRating": 0,
"genre": "rock",
"genres": [
{
"name": "rock"
},
{
"name": "progressive"
}
],
"musicBrainzId": "1234",
"song": [
{
"id": "1",
"isDir": true,
"title": "title",
"album": "album",
"artist": "artist",
"track": 1,
"year": 1985,
"genre": "Rock",
"genres": [
{
"name": "rock"
},
{
"name": "progressive"
}
],
"coverArt": "1",
"size": 8421341,
"contentType": "audio/flac",
"suffix": "flac",
"starred": "2016-03-02T20:30:00Z",
"transcodedContentType": "audio/mpeg",
"transcodedSuffix": "mp3",
"duration": 146,
"bitRate": 320,
"isVideo": false,
"bpm": 127,
"comment": "a comment"
}
]
}
}

View File

@ -0,0 +1,10 @@
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0" type="navidrome" serverVersion="v0.0.0" openSubsonic="true">
<album id="1" name="album" artist="artist" userRating="0" genre="rock" musicBrainzId="1234">
<genres name="rock"></genres>
<genres name="progressive"></genres>
<song id="1" isDir="true" title="title" album="album" artist="artist" track="1" year="1985" genre="Rock" coverArt="1" size="8421341" contentType="audio/flac" suffix="flac" starred="2016-03-02T20:30:00Z" transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="146" bitRate="320" isVideo="false" bpm="127" comment="a comment">
<genres name="rock"></genres>
<genres name="progressive"></genres>
</song>
</album>
</subsonic-response>

View File

@ -0,0 +1,14 @@
{
"status": "ok",
"version": "1.8.0",
"type": "navidrome",
"serverVersion": "v0.0.0",
"openSubsonic": true,
"album": {
"id": "",
"name": "",
"userRating": 0,
"genres": [],
"musicBrainzId": ""
}
}

View File

@ -0,0 +1,3 @@
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0" type="navidrome" serverVersion="v0.0.0" openSubsonic="true">
<album id="" name="" userRating="0" musicBrainzId=""></album>
</subsonic-response>

View File

@ -15,7 +15,14 @@
"track": 1,
"year": 1985,
"genre": "Rock",
"genres": [],
"genres": [
{
"name": "rock"
},
{
"name": "progressive"
}
],
"coverArt": "1",
"size": 8421341,
"contentType": "audio/flac",
@ -26,8 +33,8 @@
"duration": 146,
"bitRate": 320,
"isVideo": false,
"bpm": 0,
"comment": ""
"bpm": 127,
"comment": "a comment"
}
],
"id": "1",

View File

@ -1,5 +1,8 @@
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0" type="navidrome" serverVersion="v0.0.0" openSubsonic="true">
<directory id="1" name="N">
<child id="1" isDir="true" title="title" album="album" artist="artist" track="1" year="1985" genre="Rock" coverArt="1" size="8421341" contentType="audio/flac" suffix="flac" starred="2016-03-02T20:30:00Z" transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="146" bitRate="320" isVideo="false" bpm="0" comment=""></child>
<child id="1" isDir="true" title="title" album="album" artist="artist" track="1" year="1985" genre="Rock" coverArt="1" size="8421341" contentType="audio/flac" suffix="flac" starred="2016-03-02T20:30:00Z" transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="146" bitRate="320" isVideo="false" bpm="127" comment="a comment">
<genres name="rock"></genres>
<genres name="progressive"></genres>
</child>
</directory>
</subsonic-response>

View File

@ -0,0 +1,21 @@
{
"status": "ok",
"version": "1.8.0",
"type": "navidrome",
"serverVersion": "v0.0.0",
"openSubsonic": true,
"directory": {
"child": [
{
"id": "1",
"isDir": false,
"genres": [],
"isVideo": false,
"bpm": 0,
"comment": ""
}
],
"id": "",
"name": ""
}
}

View File

@ -0,0 +1,5 @@
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0" type="navidrome" serverVersion="v0.0.0" openSubsonic="true">
<directory id="" name="">
<child id="1" isDir="false" isVideo="false" bpm="0" comment=""></child>
</directory>
</subsonic-response>

View File

@ -107,59 +107,45 @@ type Indexes struct {
}
type Child struct {
Id string `xml:"id,attr" json:"id"`
Parent string `xml:"parent,attr,omitempty" json:"parent,omitempty"`
IsDir bool `xml:"isDir,attr" json:"isDir"`
Title string `xml:"title,attr,omitempty" json:"title,omitempty"`
Name string `xml:"name,attr,omitempty" json:"name,omitempty"`
Album string `xml:"album,attr,omitempty" json:"album,omitempty"`
Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"`
Track int32 `xml:"track,attr,omitempty" json:"track,omitempty"`
Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"`
Genres []ItemGenre `xml:"genres" json:"genres"`
CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
Size int64 `xml:"size,attr,omitempty" json:"size,omitempty"`
ContentType string `xml:"contentType,attr,omitempty" json:"contentType,omitempty"`
Suffix string `xml:"suffix,attr,omitempty" json:"suffix,omitempty"`
Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
TranscodedContentType string `xml:"transcodedContentType,attr,omitempty" json:"transcodedContentType,omitempty"`
TranscodedSuffix string `xml:"transcodedSuffix,attr,omitempty" json:"transcodedSuffix,omitempty"`
Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"`
BitRate int32 `xml:"bitRate,attr,omitempty" json:"bitRate,omitempty"`
Path string `xml:"path,attr,omitempty" json:"path,omitempty"`
PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"`
Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"`
DiscNumber int32 `xml:"discNumber,attr,omitempty" json:"discNumber,omitempty"`
Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"`
AlbumId string `xml:"albumId,attr,omitempty" json:"albumId,omitempty"`
ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"`
Type string `xml:"type,attr,omitempty" json:"type,omitempty"`
UserRating int32 `xml:"userRating,attr,omitempty" json:"userRating,omitempty"`
SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"`
IsVideo bool `xml:"isVideo,attr" json:"isVideo"`
BookmarkPosition int64 `xml:"bookmarkPosition,attr,omitempty" json:"bookmarkPosition,omitempty"`
Bpm int32 `xml:"bpm,attr" json:"bpm"`
Comment string `xml:"comment,attr" json:"comment"`
Id string `xml:"id,attr" json:"id"`
Parent string `xml:"parent,attr,omitempty" json:"parent,omitempty"`
IsDir bool `xml:"isDir,attr" json:"isDir"`
Title string `xml:"title,attr,omitempty" json:"title,omitempty"`
Name string `xml:"name,attr,omitempty" json:"name,omitempty"`
Album string `xml:"album,attr,omitempty" json:"album,omitempty"`
Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"`
Track int32 `xml:"track,attr,omitempty" json:"track,omitempty"`
Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"`
Genres ItemGenres `xml:"genres" json:"genres"`
CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
Size int64 `xml:"size,attr,omitempty" json:"size,omitempty"`
ContentType string `xml:"contentType,attr,omitempty" json:"contentType,omitempty"`
Suffix string `xml:"suffix,attr,omitempty" json:"suffix,omitempty"`
Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
TranscodedContentType string `xml:"transcodedContentType,attr,omitempty" json:"transcodedContentType,omitempty"`
TranscodedSuffix string `xml:"transcodedSuffix,attr,omitempty" json:"transcodedSuffix,omitempty"`
Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"`
BitRate int32 `xml:"bitRate,attr,omitempty" json:"bitRate,omitempty"`
Path string `xml:"path,attr,omitempty" json:"path,omitempty"`
PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"`
Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"`
DiscNumber int32 `xml:"discNumber,attr,omitempty" json:"discNumber,omitempty"`
Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"`
AlbumId string `xml:"albumId,attr,omitempty" json:"albumId,omitempty"`
ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"`
Type string `xml:"type,attr,omitempty" json:"type,omitempty"`
UserRating int32 `xml:"userRating,attr,omitempty" json:"userRating,omitempty"`
SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"`
IsVideo bool `xml:"isVideo,attr" json:"isVideo"`
BookmarkPosition int64 `xml:"bookmarkPosition,attr,omitempty" json:"bookmarkPosition,omitempty"`
Bpm int32 `xml:"bpm,attr" json:"bpm"`
Comment string `xml:"comment,attr" json:"comment"`
/*
<xs:attribute name="averageRating" type="sub:AverageRating" use="optional"/> <!-- Added in 1.6.0 -->
*/
}
func (c Child) MarshalJSON() ([]byte, error) {
// ensure fields that need custom default values are set properly
type Alias Child
a := struct {
Alias
}{
Alias: (Alias)(c),
}
if a.Genres == nil {
a.Genres = make([]ItemGenre, 0)
}
return json.Marshal(a)
}
type Songs struct {
Songs []Child `xml:"song" json:"song,omitempty"`
}
@ -202,36 +188,22 @@ type ArtistID3 struct {
}
type AlbumID3 struct {
Id string `xml:"id,attr" json:"id"`
Name string `xml:"name,attr" json:"name"`
Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"`
ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"`
CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"`
Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"`
PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"`
Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"`
Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"`
Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
UserRating int32 `xml:"userRating,attr" json:"userRating"`
Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"`
Genres []ItemGenre `xml:"genres" json:"genres"`
MusicBrainzId string `xml:"musicBrainzId,attr" json:"musicBrainzId"`
}
func (a AlbumID3) MarshalJSON() ([]byte, error) {
// ensure fields that need custom default values are set properly
type Alias AlbumID3
x := struct {
Alias
}{
Alias: (Alias)(a),
}
if x.Genres == nil {
x.Genres = make([]ItemGenre, 0)
}
return json.Marshal(x)
Id string `xml:"id,attr" json:"id"`
Name string `xml:"name,attr" json:"name"`
Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"`
ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"`
CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"`
Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"`
PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"`
Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"`
Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"`
Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
UserRating int32 `xml:"userRating,attr" json:"userRating"`
Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"`
Genres ItemGenres `xml:"genres" json:"genres"`
MusicBrainzId string `xml:"musicBrainzId,attr" json:"musicBrainzId"`
}
type ArtistWithAlbumsID3 struct {
@ -458,3 +430,14 @@ type OpenSubsonicExtensions struct{}
type ItemGenre struct {
Name string `xml:"name,attr" json:"name"`
}
type ItemGenres []ItemGenre
func (i ItemGenres) MarshalJSON() ([]byte, error) {
if len(i) == 0 {
return json.Marshal([]ItemGenre{})
}
type Alias []ItemGenre
a := (Alias)(i)
return json.Marshal(a)
}

View File

@ -121,6 +121,17 @@ var _ = Describe("Responses", func() {
})
Describe("Child", func() {
Context("without data", func() {
BeforeEach(func() {
response.Directory = &Directory{Child: []Child{{Id: "1"}}}
})
It("should match .XML", func() {
Expect(xml.MarshalIndent(response, "", " ")).To(MatchSnapshot())
})
It("should match .JSON", func() {
Expect(json.MarshalIndent(response, "", " ")).To(MatchSnapshot())
})
})
Context("with data", func() {
BeforeEach(func() {
response.Directory = &Directory{Id: "1", Name: "N"}
@ -130,7 +141,8 @@ var _ = Describe("Responses", func() {
Id: "1", IsDir: true, Title: "title", Album: "album", Artist: "artist", Track: 1,
Year: 1985, Genre: "Rock", CoverArt: "1", Size: 8421341, ContentType: "audio/flac",
Suffix: "flac", TranscodedContentType: "audio/mpeg", TranscodedSuffix: "mp3",
Duration: 146, BitRate: 320, Starred: &t,
Duration: 146, BitRate: 320, Starred: &t, Genres: []ItemGenre{{Name: "rock"}, {Name: "progressive"}},
Comment: "a comment", Bpm: 127,
}
response.Directory.Child = child
})
@ -144,6 +156,43 @@ var _ = Describe("Responses", func() {
})
})
Describe("AlbumWithSongsID3", func() {
BeforeEach(func() {
response.AlbumWithSongsID3 = &AlbumWithSongsID3{}
})
Context("without data", func() {
It("should match .XML", func() {
Expect(xml.MarshalIndent(response, "", " ")).To(MatchSnapshot())
})
It("should match .JSON", func() {
Expect(json.MarshalIndent(response, "", " ")).To(MatchSnapshot())
})
})
Context("with data", func() {
BeforeEach(func() {
album := AlbumID3{Id: "1", Name: "album", Artist: "artist", Genre: "rock",
Genres: []ItemGenre{{Name: "rock"}, {Name: "progressive"}}, MusicBrainzId: "1234"}
t := time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)
songs := []Child{{
Id: "1", IsDir: true, Title: "title", Album: "album", Artist: "artist", Track: 1,
Year: 1985, Genre: "Rock", CoverArt: "1", Size: 8421341, ContentType: "audio/flac",
Suffix: "flac", TranscodedContentType: "audio/mpeg", TranscodedSuffix: "mp3",
Duration: 146, BitRate: 320, Starred: &t, Genres: []ItemGenre{{Name: "rock"}, {Name: "progressive"}},
Comment: "a comment", Bpm: 127,
}}
response.AlbumWithSongsID3.AlbumID3 = album
response.AlbumWithSongsID3.Song = songs
})
It("should match .XML", func() {
Expect(xml.MarshalIndent(response, "", " ")).To(MatchSnapshot())
})
It("should match .JSON", func() {
Expect(json.MarshalIndent(response, "", " ")).To(MatchSnapshot())
})
})
})
Describe("Directory", func() {
BeforeEach(func() {
response.Directory = &Directory{Id: "1", Name: "N"}