adamint / spotify-web-api-kotlin

Spotify Web API wrapper for Kotlin, Java, JS, and Native - Targets JVM, Android, JS (browser), Native (Desktop), and Apple tvOS/iOS. Includes a Spotify Web Playback SDK wrapper for Kotlin/JS, and a spotify-auth wrapper for Kotlin/Android.
https://adamint.github.io/spotify-web-api-kotlin-docs/
MIT License
197 stars 22 forks source link

Json Parsing Exception when getting playlists #334

Closed AngryJKirk closed 7 months ago

AngryJKirk commented 8 months ago

Describe the bug Here is the stack trace:

21/02/2024
12:06:38
com.adamratzman.spotify.SpotifyException$ParseException: Unable to parse {"collaborative":false,"description":"","external_urls":{"spotify":"https://open.spotify.com/playlist/0b6zN2PUiMnjLsJ2DYiScj"},"followers":{"href":null,"total":0},"href":"https://api.spotify.com/v1/playlists/0b6zN2PUiMnjLsJ2DYiScj","id":"0b6zN2PUiMnjLsJ2DYiScj","images":null,"name":"Vas3k.Music, February 2024","owner":{"display_name":"Yaroslav","external_urls":{"spotify":"https://open.spotify.com/user/0vyvjxn41lxn5tcbemyq2fbd2"},"href":"https://api.spotify.com/v1/users/0vyvjxn41lxn5tcbemyq2fbd2","id":"0vyvjxn41lxn5tcbemyq2fbd2","type":"user","uri":"spotify:user:0vyvjxn41lxn5tcbemyq2fbd2"},"primary_color":null,"public":true,"snapshot_id":"MSw4OTdlNzVmZDFhOTQ0NGJmZGJiZjdjYjQ1M2FjM2RkODM2MjIwODM5","tracks":{"href":"https://api.spotify.com/v1/playlists/0b6zN2PUiMnjLsJ2DYiScj/tracks?offset=0&limit=0","items":[],"limit":0,"next":null,"offset":0,"previous":null,"total":0},"type":"playlist","uri":"spotify:playlist:0b6zN2PUiMnjLsJ2DYiScj"} (Unexpected JSON token at offset 270: Expected start of the array '[', but had ':' instead at path: $.images
21/02/2024
12:06:38
JSON input: .....6zN2PUiMnjLsJ2DYiScj","images":null,"name":"Vas3k.Music, Feb.....)
21/02/2024
12:06:38
    at com.adamratzman.spotify.models.serialization.SerializationUtilsKt.parseJson(SerializationUtils.kt:33)
21/02/2024
12:06:38
    at com.adamratzman.spotify.models.serialization.SerializationUtilsKt.toObject(SerializationUtils.kt:41)
21/02/2024
12:06:38
    at com.adamratzman.spotify.endpoints.pub.PlaylistApi.getPlaylist(PlaylistApi.kt:79)
21/02/2024
12:06:38
    at com.adamratzman.spotify.endpoints.pub.PlaylistApi$getPlaylist$1.invokeSuspend(PlaylistApi.kt)
21/02/2024
12:06:38
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
21/02/2024
12:06:38
    at kotlinx.coroutines.internal.ScopeCoroutine.afterResume(Scopes.kt:33)
21/02/2024
12:06:38
    at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:102)
21/02/2024
12:06:38
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
21/02/2024
12:06:38
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
21/02/2024
12:06:38
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
21/02/2024
12:06:38
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
21/02/2024
12:06:38
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
21/02/2024
12:06:38
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
21/02/2024
12:06:38
Caused by: kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 270: Expected start of the array '[', but had ':' instead at path: $.images
21/02/2024
12:06:38
JSON input: .....6zN2PUiMnjLsJ2DYiScj","images":null,"name":"Vas3k.Music, Feb.....
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:530)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.AbstractJsonLexer.fail$default(AbstractJsonLexer.kt:528)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.AbstractJsonLexer.fail$kotlinx_serialization_json(AbstractJsonLexer.kt:224)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.AbstractJsonLexer.unexpectedToken(AbstractJsonLexer.kt:207)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.StringJsonLexer.consumeNextToken(StringJsonLexer.kt:74)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.StreamingJsonDecoder.beginStructure(StreamingJsonDecoder.kt:97)
21/02/2024
12:06:38
    at kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:29)
21/02/2024
12:06:38
    at kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:70)
21/02/2024
12:06:38
    at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
21/02/2024
12:06:38
    at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableElement(StreamingJsonDecoder.kt:162)
21/02/2024
12:06:38
    at com.adamratzman.spotify.models.Playlist$$serializer.deserialize(Playlist.kt:118)
21/02/2024
12:06:38
    at com.adamratzman.spotify.models.Playlist$$serializer.deserialize(Playlist.kt:118)
21/02/2024
12:06:38
    at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:70)
21/02/2024
12:06:38
    at kotlinx.serialization.json.Json.decodeFromString(Json.kt:95)
21/02/2024
12:06:38
    at com.adamratzman.spotify.models.serialization.SerializationUtilsKt$toObject$1.invoke(SerializationUtils.kt:42)
21/02/2024
12:06:38
    at com.adamratzman.spotify.models.serialization.SerializationUtilsKt$toObject$1.invoke(SerializationUtils.kt:41)
21/02/2024
12:06:38
    at com.adamratzman.spotify.models.serialization.SerializationUtilsKt.parseJson(SerializationUtils.kt:31)
21/02/2024
12:06:38
    ... 12 common frames omitted

To Reproduce Here is how I call the service

I haven't changed anything in years except for updating the dependency version.

Expected behavior No exception should happen

Additional context

Basically what I see is this property is not expected to be null, but an empty array instead.

Probably spotify has changed something?

I am using the latest version, 4.0.2

adamint commented 8 months ago

The latest version is 4.1.0, please try with that

AngryJKirk commented 8 months ago

The same issue with 4.1.0

21/02/2024
15:15:53
com.adamratzman.spotify.SpotifyException$ParseException: Unable to parse {"collaborative":false,"description":"","external_urls":{"spotify":"https://open.spotify.com/playlist/0b6zN2PUiMnjLsJ2DYiScj"},"followers":{"href":null,"total":0},"href":"https://api.spotify.com/v1/playlists/0b6zN2PUiMnjLsJ2DYiScj","id":"0b6zN2PUiMnjLsJ2DYiScj","images":null,"name":"Vas3k.Music, February 2024","owner":{"display_name":"Yaroslav","external_urls":{"spotify":"https://open.spotify.com/user/0vyvjxn41lxn5tcbemyq2fbd2"},"href":"https://api.spotify.com/v1/users/0vyvjxn41lxn5tcbemyq2fbd2","id":"0vyvjxn41lxn5tcbemyq2fbd2","type":"user","uri":"spotify:user:0vyvjxn41lxn5tcbemyq2fbd2"},"primary_color":null,"public":true,"snapshot_id":"MSw4OTdlNzVmZDFhOTQ0NGJmZGJiZjdjYjQ1M2FjM2RkODM2MjIwODM5","tracks":{"href":"https://api.spotify.com/v1/playlists/0b6zN2PUiMnjLsJ2DYiScj/tracks?offset=0&limit=0","items":[],"limit":0,"next":null,"offset":0,"previous":null,"total":0},"type":"playlist","uri":"spotify:playlist:0b6zN2PUiMnjLsJ2DYiScj"} (Unexpected JSON token at offset 270: Expected start of the array '[', but had ':' instead at path: $.images

But that's definitely the problem with a type nullability, I guess serialization framework expects the images property to be non null, right?

adamint commented 8 months ago

I believe you’re correct. This should be an easy fix, I will try to have a release today, though Spotify keeps making previously-non null properties nullable so I need to figure out a strategy to handle these regressions. Maybe a base serializer that knows how to create “empty” versions of types, or a transformer that uses reflection to know which properties shouldn’t be null but are

if you are in need of a workaround right now, you can attach a custom serializer to whichever playlist class this is

AngryJKirk commented 8 months ago

It's fine, no hurry at all :) Thank you!