Cannot decode library songs response for a non-Apple Music item

Hi there!

I am fetching library songs using the endpoint: https://api.music.apple.com/v1/me/library/songs

Here's the code snippet -

struct Songs: Decodable {
  let data: [Song]
}

public func librarySongs() async throws {
  let url = URL(string: "https://api.music.apple.com/v1/me/library/songs")

  guard let url = url else { return }

  let dataRequest = MusicDataRequest(urlRequest: URLRequest(url: url))

  do {
    let dataResponse = try await dataRequest.response()
    print(dataResponse.debugDescription)

    let response = try JSONDecoder().decode(Songs.self, from: dataResponse.data)
  } catch {
    print("**ERROR**")
    print(error)
    print(error.localizedDescription)
    }
}

Trying to decode it using a custom struct gives me the following error. -

**ERROR**

keyNotFound(CodingKeys(stringValue: "artistName", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 20", intValue: 20), CodingKeys(stringValue: "attributes", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: \"artistName\", intValue: nil) (\"artistName\").", underlyingError: nil))

The data couldn’t be read because it is missing.

On digging through the response, I found that one of the songs doesn't have an artist name because it is just a recording of my song I added to the library through GarageBand.

In this case, what should be the approach?

Accepted Reply

Hello @snuff4,

We have included a fix for this issue in iOS 15.1 Beta 1.

I hope this helps.

Best regards,

Replies

Hello @snuff4,

Would you mind showing your custom struct?

Thanks,

Hi @JoeKun,

This is the custom struct -

struct Songs: Decodable {
  let data: [Song]
}

where Song is the new structure in MusicKit for Swift.

Hi @snuff4,

This is a bug we need to address on our end. Can you file a ticket for this on Feedback Assistant?

Thanks,

Hi @JoeKun, While creating my own framework for easy access to different Apple Music APIs, I realized I was using it wrong. It's better to decode using MusicItemCollection<> instead of creating my own structure. Then, it safely ignores the item that is not decodable due to missing information.

let response = try JSONDecoder().decode(MusicItemCollection<Song>.self, from: dataResponse.data)
  • @snuff4 @JoeKun Maybe things have changed with MusicKit since this post, but MusicItemCollection<Song>.self returns an error Type 'Song' does not conform to protocol 'MusicItem'

  • Whoops forgot I was trying to get an Album and not a Song

  • Hello @bigdaddy1,

    No, Song very much conforms to MusicItem. It always has, and we're not anticipating that changing any time soon.

    I hope this helps.

    Best regards,

Add a Comment

Hello @snuff4,

Interesting. I knew using MusicItemCollection<Song> instead of a custom struct for simple cases like these was a good alternative; for example, it allows apps to leverage MusicItemCollection builtin support for pagination to get the next batch of items.

However, I didn't remember that it would ignore problematic items like this. Thanks for sharing the tip!

Best regards,

  • Hi @JoeKun

    How does one use the built-in support for pagination in MusicItemCollection. It has the string for the next batch, but does this mean that one would have to perform a new MusicDataRequest from the Apple Music endpoint? Or is there a better way to do this directly using some MusicKit magic?

  • Hello @ashinthetray,

    Please refer to my detailed answer in the other thread you created about this specific topic.

    I hope this helps.

    Best regards,

Add a Comment

Hello @snuff4,

We have included a fix for this issue in iOS 15.1 Beta 1.

I hope this helps.

Best regards,