Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
761d87d
feat!: Spotify Web API breaking changes for 2026-02-11 (#448)
Copilot Feb 11, 2026
fbec5b9
chore(track): correct javadoc comment
dargmuesli Feb 11, 2026
786623b
ci: update signing key
dargmuesli Feb 11, 2026
d0dcfaf
10.0.0-RC1
dargmuesli Feb 11, 2026
a93ad50
feat(user): add create playlist endpoint
dargmuesli Mar 9, 2026
e3f71dc
ci(agents): add instructions
dargmuesli Mar 9, 2026
8f77f1d
ci(jitpack): use java 17
dargmuesli Mar 9, 2026
91bf5aa
Merge pull request #454 from spotify-web-api-java/copilot/add-create-…
dargmuesli Mar 9, 2026
a069569
10.0.0-RC2
dargmuesli Mar 9, 2026
557f20d
add common interfaces
fm-sys Apr 13, 2026
fcf3d08
apply copilot review suggestion
fm-sys Apr 13, 2026
01f413e
add getItems to IPlaylist to allow querying number of total tracks
fm-sys Apr 13, 2026
2b41d3e
refactor: sort imports
dargmuesli Apr 29, 2026
57276dd
fix(playlist): allow to extend the has-total interface
dargmuesli Apr 29, 2026
7ef43d2
Merge pull request #457 from fm-sys/common-interfaces
dargmuesli Apr 29, 2026
2841d7a
10.0.0-RC3
dargmuesli Apr 29, 2026
e3c0233
feat(api)!: sync specification (#460)
dargmuesli Aug 31, 2026
559da33
chore(spec): vendor spotify openapi schema for diffing (#469)
dargmuesli Aug 31, 2026
bcca48b
fix(javadoc): qualify cross-package links and document missing members
dargmuesli Aug 31, 2026
2eae502
refactor(playlists): deprecate legacy builders and reorder deprecatio…
dargmuesli Aug 31, 2026
372d951
docs(examples): rename examples to match their request classes
dargmuesli Aug 31, 2026
441e301
docs(examples): add examples for the 26 uncovered endpoints
dargmuesli Aug 31, 2026
33109e9
docs(readme): rebuild the example index from the code
dargmuesli Aug 31, 2026
e0baf0d
ci: verify examples, readme and javadoc on every build
dargmuesli Aug 31, 2026
59fec8b
Merge pull request #470 from spotify-web-api-java/fix/docs/align-java…
dargmuesli Aug 31, 2026
d280088
Merge branch 'main' into beta
dargmuesli Aug 31, 2026
d070e54
10.0.0-RC4
dargmuesli Aug 31, 2026
8dc27f7
docs: add a v9 to v10 migration guide (#471)
dargmuesli Sep 1, 2026
de189af
fix(models)!: deserialize model objects reflectively with gson (#473)
dargmuesli Sep 1, 2026
30ea468
refactor(renovate): add file extension
dargmuesli Sep 1, 2026
ce5f922
docs: correct the 9.4.0 deprecation count in the migration guide
dargmuesli Sep 1, 2026
7f65347
10.0.0-RC5
dargmuesli Sep 1, 2026
b22d303
fix(build): keep the automatic module name in the released jar
dargmuesli Sep 1, 2026
f46781a
10.0.0-RC6
dargmuesli Sep 1, 2026
384e973
feat(build)!: ship an explicit JPMS module and vendor the country cod…
dargmuesli Sep 2, 2026
9bd564a
10.0.0-RC7
dargmuesli Sep 2, 2026
e60028f
refactor(build): compile the examples as their own module (#475)
dargmuesli Sep 2, 2026
fe09274
docs(api): clarify November 2024 restriction notices (#477)
dargmuesli Sep 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(models)!: deserialize model objects reflectively with gson (#473)
  • Loading branch information
dargmuesli authored Sep 1, 2026
commit de189afe28618d3567d4245c7e53b6dfb2db796b
21 changes: 18 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ This file provides context for AI coding agents working in this repository.

- **Group ID:** `se.michaelthelin.spotify`
- **Artifact ID:** `spotify-web-api-java`
- **Current Version:** `10.0.0-RC1`
- **Build Tool:** Maven (`pom.xml`)
- **Java Version:** 17+
- **Java Version:** compiled with `--release 9`; CI builds on JDK 17 and 25

## Repository Structure

Expand Down Expand Up @@ -49,7 +48,6 @@ Create `src/main/java/se/michaelthelin/spotify/requests/data/<category>/<Endpoin

Key patterns:
- Extend `AbstractDataRequest<ReturnType>` (or `AbstractDataPagingRequest` for paginated results).
- Annotate with `@JsonDeserialize(builder = <ClassName>.Builder.class)`.
- Implement `execute()` which calls `getJson()`, `postJson()`, `putJson()`, or `deleteJson()` as appropriate.
- Add a `static final class Builder` with:
- Path parameters set via `setPathParameter("key", value)`
Expand Down Expand Up @@ -86,6 +84,19 @@ Extend `AbstractDataTest<ReturnType>`. Tests should:

Common test constants are in `ITest.java` (e.g., `ITest.NAME`, `ITest.ID_PLAYLIST`, `ITest.PUBLIC`).

### 5. Add an example and index it

Create `examples/.../<EndpointName>Example.java` and link it from the example index in `README.md`.
Mark the link with ⚠️ if the request class carries `@Deprecated`.

`./ci/check-docs.py` enforces all of this and runs in CI.
It checks that every `SpotifyApi` method has an example, that example file names match their request class, that the README index is complete and its ⚠️ markers match the code, that each request's verb and path exist in `spec/openapi.yaml` with matching deprecation, and that every current-API name written in `MIGRATION.md` still resolves.

### Renaming or removing public API

Record it in `MIGRATION.md` under the relevant `#### ` heading.
Names that no longer exist have to sit in a table column whose header contains "v9", or inside a code fence under a `// v9` marker, otherwise the docs check reports them as stale.

## Building and Testing

```bash
Expand All @@ -104,6 +115,10 @@ mvn test -Dtest="*Playlist*"

## Key Conventions

- **Model objects are deserialized reflectively** by the shared Gson in
`model_objects/ModelObjectGson.java`, so a new field needs no parsing code.
Add `@SerializedName` only when the wire name is not the snake_case form of the field,
and add a type adapter only for a shape reflection cannot express.
- **Trailing underscores** on Java-reserved words: e.g., `public_` for the `public` field.
- **Assertions** in tests are imported from both JUnit 5 (`org.junit.jupiter.api.Assertions`) and the project's own `se.michaelthelin.spotify.Assertions`.
- **Nullable fields** from the API should be tested with `assertNull(...)` when the fixture returns `null`.
Expand Down
27 changes: 27 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,31 @@ There is no replacement.
| `Track` | `getAvailableMarkets()`, `getLinkedFrom()`, `getPopularity()` |
| `TrackSimplified` | `getAvailableMarkets()`, `getLinkedFrom()` |

#### Removed classes

Nothing in the library referred to these any more, in most cases because 10.0.0 dropped the getter that used them.

| v9 type | Why it went |
|---|---|
| `AlbumGroup` | backed `AlbumSimplified.getAlbumGroup()`, which the specification deprecated |
| `ProductType` | backed the user product getter, which the specification deprecated |
| `PlaylistTrackPosition` | never referenced by any request or model object |
| `Paging.JsonUtil`, `PagingCursorbased.JsonUtil` | resolved their type argument to a parameterized type rather than a class, so instantiating either always threw |

A `Paging` object is built through the JsonUtil of the type it contains, which is how every request already built one.
The `IModelObject` array helper that took an explicit element class is gone as well, having had no callers.

#### New getters and model objects

`Album` and `AlbumSimplified` gained `getTotalTracks()`, `AlbumSimplified` also `getIsPlayable()`, `Episode` and `EpisodeSimplified` `getHtmlDescription()`, `User` `getAccountId()` and `getExplicitContent()`, and `SearchResult` `getAudiobooks()`.

Audiobooks and chapters are new: `Audiobook`, `AudiobookSimplified`, `Chapter`, `ChapterSimplified`, `ChapterRestriction`, `Author` and `Narrator`.
`ExplicitContentSettings` backs the new `User.getExplicitContent()`.

Three getters that always returned `null` in 9.4.0 now return a value, because the parser was reading a key the API does not send.
`AudioAnalysisTrack` fixes `getWindowSeconds()` and `getEndOfFadeIn()`, and `AudioAnalysisSection` fixes `getMode()`.
Code that null-checked them will now take the other branch.

Seven interfaces were extracted so that full and simplified objects can be handled through one type: `IAlbum`, `IArtist`, `IEpisode`, `IPlaylist`, `IShow`, `ITrack` and `IHasTotal`.

### New in 10.0.0
Expand Down Expand Up @@ -204,6 +222,15 @@ Playlist items on the `/items` path, replacing the `/tracks` path:

And `getAvailableMarkets` ⚠️ for `GET /markets`.

### Deserialization

Model objects are deserialized reflectively by Gson.
The Jackson annotations every model carried are gone, along with the Jackson dependency itself, because nothing in the library ever constructed an ObjectMapper.

This only affects you if you fed these model classes into your own ObjectMapper.
The `@JsonDeserialize` annotations gave you builder-based deserialization for free, and you now have to configure that yourself.
Nothing changes for code that goes through the library.

### Deprecations

49 of the 114 request builders carry `@Deprecated`, up from 1 in 9.4.0.
Expand Down
11 changes: 6 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,6 @@
<version>6.1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.22.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down Expand Up @@ -200,6 +195,11 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.12.0</version>
<configuration>
<!-- accessors and builder setters in model_objects carry no prose of their own,
so only broken syntax and dead references should be reported -->
<doclint>all,-missing</doclint>
</configuration>
</plugin>
</plugins>
</build>
Expand Down Expand Up @@ -261,6 +261,7 @@
</execution>
</executions>
<configuration>
<doclint>all,-missing</doclint>
<outputDirectory>${project.basedir}/</outputDirectory>
</configuration>
</plugin>
Expand Down
54 changes: 0 additions & 54 deletions src/main/java/se/michaelthelin/spotify/enums/AlbumGroup.java

This file was deleted.

56 changes: 0 additions & 56 deletions src/main/java/se/michaelthelin/spotify/enums/ProductType.java

This file was deleted.

Loading
Loading