Skip to content

Commit c297660

Browse files
committed
remove org.json except in to(Linked/Paging) helpers
Signed-off-by: Adam Ratzman <adam@adamratzman.com>
1 parent da2445f commit c297660

File tree

7 files changed

+113
-92
lines changed

7 files changed

+113
-92
lines changed

build.gradle

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ repositories {
3232

3333
dependencies {
3434
// Actual library dependencies
35-
implementation(group: 'org.json', name: 'json', version: '20180130')
36-
3735
implementation 'com.beust:klaxon:5.0.1'
3836

3937
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
@@ -49,8 +47,9 @@ dependencies {
4947
}
5048

5149
testImplementation('org.junit.jupiter:junit-jupiter-api:5.2.0')
50+
implementation(group: 'org.json', name: 'json', version: '20180130')
5251
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
53-
testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
52+
5453
}
5554

5655
spotless {

src/main/kotlin/com/adamratzman/spotify/endpoints/client/ClientPlayerAPI.kt

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import com.adamratzman.spotify.utils.encode
2121
import com.adamratzman.spotify.utils.toCursorBasedPagingObject
2222
import com.adamratzman.spotify.utils.toInnerObject
2323
import com.adamratzman.spotify.utils.toObject
24-
import org.json.JSONObject
24+
import com.beust.klaxon.JsonObject
2525
import java.util.function.Supplier
2626

2727
/**
@@ -47,7 +47,7 @@ class ClientPlayerAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
4747
})
4848
}
4949

50-
fun getRecentlyPlayed(): SpotifyRestActionPaging<PlayHistory,CursorBasedPagingObject<PlayHistory>> {
50+
fun getRecentlyPlayed(): SpotifyRestActionPaging<PlayHistory, CursorBasedPagingObject<PlayHistory>> {
5151
return toActionPaging(Supplier {
5252
get(EndpointBuilder("/me/player/recently-played").toString()).toCursorBasedPagingObject<PlayHistory>(
5353
endpoint = this
@@ -156,17 +156,18 @@ class ClientPlayerAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
156156
): SpotifyRestAction<Unit> {
157157
return toAction(Supplier {
158158
val url = EndpointBuilder("/me/player/play").with("device_id", deviceId).toString()
159-
val body = JSONObject()
159+
val body = JsonObject()
160160
when {
161-
album != null -> body.put("context_uri", AlbumURI(album).uri)
162-
artist != null -> body.put("context_uri", ArtistURI(artist).uri)
163-
playlist != null -> body.put("context_uri", playlist.uri)
164-
tracksToPlay.isNotEmpty() -> body.put("uris", tracksToPlay.map { TrackURI(it).uri })
161+
album != null -> body["context_uri"] = AlbumURI(album).uri
162+
artist != null -> body["context_uri"] = ArtistURI(artist).uri
163+
playlist != null -> body["context_uri"] = playlist.uri
164+
tracksToPlay.isNotEmpty() -> body["uris"] = tracksToPlay.map { TrackURI(it).uri }
165165
}
166-
if (body.keySet().isNotEmpty()) {
167-
if (offsetNum != null) body.put("offset", JSONObject().put("position", offsetNum))
168-
else if (offsetTrackId != null) body.put("offset", JSONObject().put("uri", TrackURI(offsetTrackId).uri))
169-
put(url, body.toString())
166+
if (body.keys.isNotEmpty()) {
167+
if (offsetNum != null) body["offset"] = JsonObject().apply { this["position"] = offsetNum }
168+
else if (offsetTrackId != null) body["offset"] =
169+
JsonObject().apply { this["uri"] = TrackURI(offsetTrackId).uri }
170+
put(url, body.toJsonString())
170171
} else put(url)
171172
Unit
172173
})

src/main/kotlin/com/adamratzman/spotify/endpoints/client/ClientPlaylistAPI.kt

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import com.adamratzman.spotify.utils.UserURI
1818
import com.adamratzman.spotify.utils.encode
1919
import com.adamratzman.spotify.utils.toObject
2020
import com.adamratzman.spotify.utils.toPagingObject
21-
import org.json.JSONArray
22-
import org.json.JSONObject
21+
import com.beust.klaxon.JsonArray
22+
import com.beust.klaxon.JsonObject
2323
import java.awt.image.BufferedImage
2424
import java.io.ByteArrayOutputStream
2525
import java.io.File
@@ -57,14 +57,14 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
5757
): SpotifyRestAction<Playlist> {
5858
if (name.isEmpty()) throw BadRequestException(ErrorObject(400, "Name cannot be empty"))
5959
return toAction(Supplier {
60-
val json = JSONObject()
61-
json.put("name", name)
62-
if (description != null) json.put("description", description)
63-
if (public != null) json.put("public", public)
64-
if (collaborative != null) json.put("collaborative", collaborative)
60+
val json = JsonObject()
61+
json["name"] = name
62+
if (description != null) json["description"] = description
63+
if (public != null) json["public"] = public
64+
if (collaborative != null) json["collaborative"] = collaborative
6565
post(
6666
EndpointBuilder("/users/${UserURI(user).id.encode()}/playlists").toString(),
67-
json.toString()
67+
json.toJsonString()
6868
).toObject<Playlist>(api)
6969
})
7070
}
@@ -81,10 +81,13 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
8181
* @throws BadRequestException if any invalid track ids is provided or the playlist is not found
8282
*/
8383
fun addTracksToPlaylist(playlist: String, vararg tracks: String, position: Int? = null): SpotifyRestAction<Unit> {
84-
val json = JSONObject().put("uris", tracks.map { TrackURI(TrackURI(it).id.encode()).uri })
85-
if (position != null) json.put("position", position)
84+
val json = JsonObject().apply { this["uris"] = tracks.map { TrackURI(TrackURI(it).id.encode()).uri } }
85+
if (position != null) json["position"] = position
8686
return toAction(Supplier {
87-
post(EndpointBuilder("/playlists/${PlaylistURI(playlist).id.encode()}/tracks").toString(), json.toString())
87+
post(
88+
EndpointBuilder("/playlists/${PlaylistURI(playlist).id.encode()}/tracks").toString(),
89+
json.toJsonString()
90+
)
8891
Unit
8992
})
9093
}
@@ -107,14 +110,14 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
107110
collaborative: Boolean? = null,
108111
description: String? = null
109112
): SpotifyRestAction<Unit> {
110-
val json = JSONObject()
111-
if (name != null) json.put("name", name)
112-
if (public != null) json.put("public", public)
113-
if (collaborative != null) json.put("collaborative", collaborative)
114-
if (description != null) json.put("description", description)
115-
if (json.length() == 0) throw IllegalArgumentException("At least one option must not be null")
113+
val json = JsonObject()
114+
if (name != null) json["name"] = name
115+
if (public != null) json["public"] = public
116+
if (collaborative != null) json["collaborative"] = collaborative
117+
if (description != null) json["description"] = description
118+
if (json.isEmpty()) throw IllegalArgumentException("At least one option must not be null")
116119
return toAction(Supplier {
117-
put(EndpointBuilder("/playlists/${PlaylistURI(playlist).id.encode()}").toString(), json.toString())
120+
put(EndpointBuilder("/playlists/${PlaylistURI(playlist).id.encode()}").toString(), json.toJsonString())
118121
Unit
119122
})
120123
}
@@ -130,7 +133,7 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
130133
fun getClientPlaylists(
131134
limit: Int? = null,
132135
offset: Int? = null
133-
): SpotifyRestActionPaging<SimplePlaylist,PagingObject<SimplePlaylist>> {
136+
): SpotifyRestActionPaging<SimplePlaylist, PagingObject<SimplePlaylist>> {
134137
if (limit != null && limit !in 1..50) throw IllegalArgumentException("Limit must be between 1 and 50. Provided $limit")
135138
if (offset != null && offset !in 0..100000) throw IllegalArgumentException("Offset must be between 0 and 100,000. Provided $limit")
136139
return toActionPaging(Supplier {
@@ -190,13 +193,15 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
190193
snapshotId: String? = null
191194
): SpotifyRestAction<Snapshot> {
192195
return toAction(Supplier {
193-
val json = JSONObject()
194-
json.put("range_start", reorderRangeStart)
195-
json.put("insert_before", insertionPoint)
196-
if (reorderRangeLength != null) json.put("range_length", reorderRangeLength)
197-
if (snapshotId != null) json.put("snapshot_id", snapshotId)
198-
put(EndpointBuilder("/playlists/${PlaylistURI(playlist).id.encode()}/tracks").toString(), json.toString())
199-
.toObject<Snapshot>(api)
196+
val json = JsonObject()
197+
json["range_start"] = reorderRangeStart
198+
json["insert_before"] = insertionPoint
199+
if (reorderRangeLength != null) json["range_length"] = reorderRangeLength
200+
if (snapshotId != null) json["snapshot_id"] = snapshotId
201+
put(
202+
EndpointBuilder("/playlists/${PlaylistURI(playlist).id.encode()}/tracks").toString(),
203+
json.toJsonString()
204+
).toObject<Snapshot>(api)
200205
})
201206
}
202207

@@ -211,9 +216,12 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
211216
*/
212217
fun setPlaylistTracks(playlist: String, vararg tracks: String): SpotifyRestAction<Unit> {
213218
return toAction(Supplier {
214-
val json = JSONObject()
215-
json.put("uris", tracks.map { TrackURI(TrackURI(it).id.encode()).uri })
216-
put(EndpointBuilder("/playlists/${PlaylistURI(playlist).id.encode()}/tracks").toString(), json.toString())
219+
val json = JsonObject()
220+
json["uris"] = tracks.map { TrackURI(TrackURI(it).id.encode()).uri }
221+
put(
222+
EndpointBuilder("/playlists/${PlaylistURI(playlist).id.encode()}/tracks").toString(),
223+
json.toJsonString()
224+
)
217225
Unit
218226
})
219227
}
@@ -298,14 +306,16 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
298306
return toAction(Supplier {
299307
if (tracks.isEmpty()) throw IllegalArgumentException("You need to provide at least one track to remove")
300308

301-
val json = JSONObject().also { if (snapshotId != null) it.put("snapshot_id", snapshotId) }
309+
val json = JsonObject().apply { if (snapshotId != null) this["snapshot_id"] = snapshotId }
302310

303311
tracks.map { (track, positions) ->
304-
JSONObject().put("uri", TrackURI(track).uri)
305-
.also { if (positions?.positions?.isNotEmpty() == true) it.put("positions", positions.positions) }
306-
}.let { json.put("tracks", JSONArray(it)) }
312+
JsonObject().apply {
313+
this["uri"] = TrackURI(track).uri
314+
if (positions?.positions?.isNotEmpty() == true) this.put("positions", positions.positions)
315+
}.also { if (positions?.positions?.isNotEmpty() == true) it["positions"] = positions.positions }
316+
}.let { json.put("tracks", JsonArray(it)) }
307317
delete(
308-
EndpointBuilder("/playlists/${PlaylistURI(playlist).id}/tracks").toString(), body = json.toString()
318+
EndpointBuilder("/playlists/${PlaylistURI(playlist).id}/tracks").toString(), body = json.toJsonString()
309319
)
310320
})
311321
}

src/main/kotlin/com/adamratzman/spotify/endpoints/public/BrowseAPI.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@ import com.adamratzman.spotify.utils.SpotifyCategory
2020
import com.adamratzman.spotify.utils.SpotifyEndpoint
2121
import com.adamratzman.spotify.utils.TrackURI
2222
import com.adamratzman.spotify.utils.encode
23-
import com.adamratzman.spotify.utils.map
23+
import com.adamratzman.spotify.utils.toInnerArray
2424
import com.adamratzman.spotify.utils.toObject
2525
import com.adamratzman.spotify.utils.toPagingObject
26-
import org.json.JSONObject
2726
import java.text.SimpleDateFormat
2827
import java.time.Instant
2928
import java.util.Date
@@ -41,8 +40,10 @@ class BrowseAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
4140
*/
4241
fun getAvailableGenreSeeds(): SpotifyRestAction<List<String>> {
4342
return toAction(Supplier {
44-
JSONObject(get(EndpointBuilder("/recommendations/available-genre-seeds").toString())).getJSONArray("genres")
45-
.map { it.toString() }
43+
get(EndpointBuilder("/recommendations/available-genre-seeds").toString()).toInnerArray<String>(
44+
"genres",
45+
api
46+
)
4647
})
4748
}
4849

@@ -60,7 +61,7 @@ class BrowseAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
6061
limit: Int? = null,
6162
offset: Int? = null,
6263
market: Market? = null
63-
): SpotifyRestActionPaging<SimpleAlbum,PagingObject<SimpleAlbum>> {
64+
): SpotifyRestActionPaging<SimpleAlbum, PagingObject<SimpleAlbum>> {
6465
return toActionPaging(Supplier {
6566
get(
6667
EndpointBuilder("/browse/new-releases").with("limit", limit).with("offset", offset).with(
@@ -130,7 +131,7 @@ class BrowseAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
130131
offset: Int? = null,
131132
locale: String? = null,
132133
market: Market? = null
133-
): SpotifyRestActionPaging<SpotifyCategory,PagingObject<SpotifyCategory>> {
134+
): SpotifyRestActionPaging<SpotifyCategory, PagingObject<SpotifyCategory>> {
134135
return toActionPaging(Supplier {
135136
get(
136137
EndpointBuilder("/browse/categories").with("limit", limit).with("offset", offset).with(
@@ -185,7 +186,7 @@ class BrowseAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
185186
limit: Int? = null,
186187
offset: Int? = null,
187188
market: Market? = null
188-
): SpotifyRestActionPaging<SimplePlaylist,PagingObject<SimplePlaylist>> {
189+
): SpotifyRestActionPaging<SimplePlaylist, PagingObject<SimplePlaylist>> {
189190
return toActionPaging(Supplier {
190191
get(
191192
EndpointBuilder("/browse/categories/${categoryId.encode()}/playlists").with(

src/main/kotlin/com/adamratzman/spotify/utils/Helpers.kt

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import com.adamratzman.spotify.main.SpotifyAPI
66
import com.adamratzman.spotify.main.SpotifyException
77
import com.beust.klaxon.Json
88
import com.beust.klaxon.Klaxon
9-
import org.json.JSONArray
109
import org.json.JSONObject
1110
import java.io.InvalidObjectException
1211
import java.net.URLEncoder
@@ -75,7 +74,14 @@ internal inline fun <reified T> String.toObject(o: SpotifyAPI?): T {
7574

7675
internal inline fun <reified T> String.toArray(o: SpotifyAPI?): List<T> {
7776
val klaxon = o?.klaxon ?: Klaxon()
78-
return klaxon.parseArray<T>(this) ?: throw SpotifyException(
77+
return klaxon.parseArray<T>(this)?.apply {
78+
if (o != null) {
79+
forEach { obj ->
80+
if (obj is Linkable) obj.api = o
81+
if (obj is AbstractPagingObject<*>) obj.endpoint = o.tracks
82+
}
83+
}
84+
} ?: throw SpotifyException(
7985
"Unable to parse $this",
8086
IllegalArgumentException("$this not found")
8187
)
@@ -85,15 +91,17 @@ internal inline fun <reified T> String.toPagingObject(
8591
innerObjectName: String? = null,
8692
endpoint: SpotifyEndpoint
8793
): PagingObject<T> {
88-
val jsonObject = if (innerObjectName != null) JSONObject(this).getJSONObject(innerObjectName) else JSONObject(this)
94+
val jsonObject = endpoint.api.klaxon.parseJsonObject(this.reader())
95+
.let { if (innerObjectName != null) it.obj(innerObjectName)!! else it }
96+
8997
return PagingObject(
90-
jsonObject.getString("href"),
91-
jsonObject.getJSONArray("items").map { it.toString().toObject<T>(endpoint.api) },
92-
jsonObject.getInt("limit"),
93-
jsonObject.get("next") as? String,
94-
jsonObject.get("offset") as Int,
95-
jsonObject.get("previous") as? String,
96-
jsonObject.getInt("total")
98+
jsonObject.string("href")!!,
99+
JSONObject(jsonObject.toJsonString()).getJSONArray("items").toString().toArray<T>(endpoint.api),
100+
jsonObject.int("limit")!!,
101+
jsonObject.string("next"),
102+
jsonObject.int("offset")!!,
103+
jsonObject.string("previous"),
104+
jsonObject.int("total")!!
97105
).apply {
98106
this.endpoint = endpoint
99107
this.itemClazz = T::class.java
@@ -104,35 +112,42 @@ internal inline fun <reified T> String.toCursorBasedPagingObject(
104112
innerObjectName: String? = null,
105113
endpoint: SpotifyEndpoint
106114
): CursorBasedPagingObject<T> {
107-
val jsonObject = if (innerObjectName != null) JSONObject(this).getJSONObject(innerObjectName) else JSONObject(this)
115+
val jsonObject = endpoint.api.klaxon.parseJsonObject(this.reader())
116+
.let { if (innerObjectName != null) it.obj(innerObjectName)!! else it }
117+
108118
return CursorBasedPagingObject(
109-
jsonObject.getString("href"),
110-
jsonObject.getJSONArray("items").map { it.toString().toObject<T>(endpoint.api) },
111-
jsonObject.getInt("limit"),
112-
jsonObject.get("next") as? String,
113-
jsonObject.getJSONObject("cursors").toString().toObject(endpoint.api),
114-
if (jsonObject.keySet().contains("total")) jsonObject.getInt("total") else -1
119+
jsonObject.string("href")!!,
120+
JSONObject(jsonObject.toJsonString()).getJSONArray("items").toString().toArray<T>(endpoint.api),
121+
jsonObject.int("limit")!!,
122+
jsonObject.string("next"),
123+
endpoint.api.klaxon.parseFromJsonObject(jsonObject.obj("cursors")!!)!!,
124+
if (jsonObject.containsKey("total")) jsonObject.int("total")!! else -1
115125
).apply {
116126
this.endpoint = endpoint
117127
this.itemClazz = T::class.java
118128
}
119129
}
120130

121131
internal inline fun <reified T> String.toLinkedResult(api: SpotifyAPI): LinkedResult<T> {
122-
val jsonObject = JSONObject(this)
132+
val jsonObject = api.klaxon.parseJsonObject(this.reader())
123133
return LinkedResult(
124-
jsonObject.getString("href"),
125-
jsonObject.getJSONArray("items").map { it.toString().toObject<T>(api) })
134+
jsonObject.string("href")!!,
135+
JSONObject(jsonObject.toJsonString()).getJSONArray("items").toString().toArray<T>(api)
136+
)
126137
}
127138

128139
internal inline fun <reified T> String.toInnerObject(innerName: String, api: SpotifyAPI): T {
129-
return JSONObject(this).let { it.optJSONObject(innerName) ?: it.getJSONArray(innerName) }
130-
.toString().toObject(api)
140+
val jsonObject = api.klaxon.parseJsonObject(this.reader())
141+
142+
return jsonObject.obj(innerName)?.let { api.klaxon.parseFromJsonObject<T>(it) }
143+
?: throw SpotifyException("Unable to parse $this into $innerName (${T::class})", IllegalArgumentException())
131144
}
132145

133146
internal inline fun <reified T> String.toInnerArray(innerName: String, api: SpotifyAPI): List<T> {
134-
return JSONObject(this).let { it.optJSONObject(innerName) ?: it.getJSONArray(innerName) }
135-
.toString().toArray(api)
147+
val jsonObject = api.klaxon.parseJsonObject(this.reader())
148+
149+
return jsonObject.array(innerName)
150+
?: throw SpotifyException("Unable to parse $this into $innerName (${T::class})", IllegalArgumentException())
136151
}
137152

138153
internal fun <T> catch(function: () -> T): T? {
@@ -141,10 +156,4 @@ internal fun <T> catch(function: () -> T): T? {
141156
} catch (e: BadRequestException) {
142157
null
143158
}
144-
}
145-
146-
internal inline fun <R> JSONArray.map(transform: (Any) -> R): List<R> {
147-
return List(this.length()) {
148-
transform(this.get(it))
149-
}
150-
}
159+
}

0 commit comments

Comments
 (0)