-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create Json-specific kotlinx.serialization converter factory
- Loading branch information
Showing
10 changed files
with
301 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# kotlinx.serialization Converter | ||
|
||
A `Converter` which uses [kotlinx.serialization.json][1] for serialization. | ||
|
||
Given a `Json`, call `asConverterFactory()` in order to | ||
create a `Converter.Factory`. | ||
|
||
```kotlin | ||
val retrofit = Retrofit.Builder() | ||
.baseUrl("https://example.com/") | ||
.addConverterFactory(Json.asConverterFactory()) | ||
.build() | ||
``` | ||
|
||
|
||
## Download | ||
|
||
Download [the latest JAR][2] or grab via [Maven][3]: | ||
```xml | ||
<dependency> | ||
<groupId>com.squareup.retrofit2</groupId> | ||
<artifactId>converter-kotlinx-serialization-json</artifactId> | ||
<version>latest.version</version> | ||
</dependency> | ||
``` | ||
or [Gradle][3]: | ||
```groovy | ||
implementation 'com.squareup.retrofit2:converter-kotlinx-serialization-json:latest.version' | ||
``` | ||
|
||
Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. | ||
|
||
|
||
|
||
[1]: https://github.com/Kotlin/kotlinx.serialization | ||
[2]: https://search.maven.org/remote_content?g=com.squareup.retrofit2&a=converter-kotlinx-serialization-json&v=LATEST | ||
[3]: http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.squareup.retrofit2%22%20a%3A%22converter-kotlinx-serialization-json%22 | ||
[snap]: https://s01.oss.sonatype.org/content/repositories/snapshots/ |
16 changes: 16 additions & 0 deletions
16
retrofit-converters/kotlinx-serialization-json/build.gradle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
apply plugin: 'org.jetbrains.kotlin.jvm' | ||
apply plugin: 'org.jetbrains.kotlin.plugin.serialization' | ||
apply plugin: 'com.vanniktech.maven.publish' | ||
apply plugin: 'org.jetbrains.dokka' | ||
|
||
dependencies { | ||
implementation project(':retrofit-converters:kotlinx-serialization') | ||
|
||
api projects.retrofit | ||
api libs.kotlinx.serialization.json | ||
|
||
testImplementation libs.junit | ||
testImplementation libs.okhttp.mockwebserver | ||
testImplementation libs.kotlinx.serialization.proto | ||
testImplementation libs.kotlinx.serialization.json | ||
} |
3 changes: 3 additions & 0 deletions
3
retrofit-converters/kotlinx-serialization-json/gradle.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
POM_ARTIFACT_ID=converter-kotlinx-serialization-json | ||
POM_NAME=Converter: kotlinx.serialization.json | ||
POM_DESCRIPTION=A Retrofit Converter which uses kotlinx.serialization.json for serialization. |
20 changes: 20 additions & 0 deletions
20
...json/src/main/java/retrofit2/converter/kotlinx/serialization/json/JsonConverterFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package retrofit2.converter.kotlinx.serialization.json | ||
|
||
import kotlinx.serialization.json.Json | ||
import okhttp3.MediaType | ||
import retrofit2.Converter | ||
import retrofit2.converter.kotlinx.serialization.Factory | ||
import retrofit2.converter.kotlinx.serialization.Serializer | ||
|
||
/** | ||
* Return a [Converter.Factory] which uses Kotlin serialization for Json-based payloads. | ||
* | ||
* Because Kotlin serialization is so flexible in the types it supports, this converter assumes | ||
* that it can handle all types. If you are mixing this with something else, you must add this | ||
* instance last to allow the other converters a chance to see their types. | ||
*/ | ||
@JvmName("create") | ||
fun Json.asConverterFactory(): Converter.Factory { | ||
val contentType = MediaType.get("application/json; charset=UTF-8") | ||
return Factory(contentType, Serializer.FromString(this)) | ||
} |
85 changes: 85 additions & 0 deletions
85
.../kotlinx/serialization/json/KotlinxJsonSerializationConverterFactoryContextualListTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package retrofit2.converter.kotlinx.serialization.json | ||
|
||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.descriptors.PrimitiveKind | ||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor | ||
import kotlinx.serialization.encoding.Decoder | ||
import kotlinx.serialization.encoding.Encoder | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.modules.SerializersModule | ||
import kotlinx.serialization.modules.contextual | ||
import okhttp3.mockwebserver.MockResponse | ||
import okhttp3.mockwebserver.MockWebServer | ||
import org.junit.Assert | ||
import org.junit.Before | ||
import org.junit.Rule | ||
import org.junit.Test | ||
import retrofit2.Call | ||
import retrofit2.Retrofit | ||
import retrofit2.http.Body | ||
import retrofit2.http.GET | ||
import retrofit2.http.POST | ||
|
||
class KotlinxJsonSerializationConverterFactoryContextualListTest { | ||
@get:Rule | ||
val server = MockWebServer() | ||
|
||
private lateinit var service: Service | ||
|
||
interface Service { | ||
@GET("/") | ||
fun deserialize(): Call<List<User>> | ||
|
||
@POST("/") | ||
fun serialize(@Body users: List<User>): Call<Void?> | ||
} | ||
|
||
data class User(val name: String) | ||
|
||
object UserSerializer : KSerializer<User> { | ||
override val descriptor = PrimitiveSerialDescriptor("User", PrimitiveKind.STRING) | ||
|
||
override fun deserialize(decoder: Decoder): User = | ||
decoder.decodeSerializableValue(UserResponse.serializer()).run { | ||
User(name) | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: User): Unit = | ||
encoder.encodeSerializableValue(UserResponse.serializer(), UserResponse(value.name)) | ||
|
||
@Serializable | ||
private data class UserResponse(val name: String) | ||
} | ||
|
||
private val json = Json { | ||
serializersModule = SerializersModule { | ||
contextual(UserSerializer) | ||
} | ||
} | ||
|
||
@Before | ||
fun setUp() { | ||
val retrofit = Retrofit.Builder() | ||
.baseUrl(server.url("/")) | ||
.addConverterFactory(json.asConverterFactory()) | ||
.build() | ||
service = retrofit.create(Service::class.java) | ||
} | ||
|
||
@Test | ||
fun deserialize() { | ||
server.enqueue(MockResponse().setBody("""[{"name":"Bob"}]""")) | ||
val user = service.deserialize().execute().body()!! | ||
Assert.assertEquals(listOf(User("Bob")), user) | ||
} | ||
|
||
@Test | ||
fun serialize() { | ||
server.enqueue(MockResponse()) | ||
service.serialize(listOf(User("Bob"))).execute() | ||
val request = server.takeRequest() | ||
Assert.assertEquals("""[{"name":"Bob"}]""", request.body.readUtf8()) | ||
Assert.assertEquals("application/json; charset=UTF-8", request.headers["Content-Type"]) | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
...rter/kotlinx/serialization/json/KotlinxSerializationJsonConverterFactoryContextualTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package retrofit2.converter.kotlinx.serialization.json | ||
|
||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.descriptors.PrimitiveKind | ||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor | ||
import kotlinx.serialization.encoding.Decoder | ||
import kotlinx.serialization.encoding.Encoder | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.modules.SerializersModule | ||
import kotlinx.serialization.modules.contextual | ||
import okhttp3.mockwebserver.MockResponse | ||
import okhttp3.mockwebserver.MockWebServer | ||
import org.junit.Assert.assertEquals | ||
import org.junit.Before | ||
import org.junit.Rule | ||
import org.junit.Test | ||
import retrofit2.Call | ||
import retrofit2.Retrofit | ||
import retrofit2.http.Body | ||
import retrofit2.http.GET | ||
import retrofit2.http.POST | ||
|
||
class KotlinxSerializationJsonConverterFactoryContextualTest { | ||
@get:Rule | ||
val server = MockWebServer() | ||
|
||
private lateinit var service: Service | ||
|
||
interface Service { | ||
@GET("/") | ||
fun deserialize(): Call<User> | ||
|
||
@POST("/") | ||
fun serialize(@Body user: User): Call<Void?> | ||
} | ||
|
||
data class User(val name: String) | ||
|
||
object UserSerializer : KSerializer<User> { | ||
override val descriptor = PrimitiveSerialDescriptor("User", PrimitiveKind.STRING) | ||
|
||
override fun deserialize(decoder: Decoder): User = | ||
decoder.decodeSerializableValue(UserResponse.serializer()).run { | ||
User(name) | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: User): Unit = | ||
encoder.encodeSerializableValue(UserResponse.serializer(), UserResponse(value.name)) | ||
|
||
@Serializable | ||
private data class UserResponse(val name: String) | ||
} | ||
|
||
private val json = Json { | ||
serializersModule = SerializersModule { | ||
contextual(UserSerializer) | ||
} | ||
} | ||
|
||
@Before | ||
fun setUp() { | ||
val retrofit = Retrofit.Builder() | ||
.baseUrl(server.url("/")) | ||
.addConverterFactory(json.asConverterFactory()) | ||
.build() | ||
service = retrofit.create(Service::class.java) | ||
} | ||
|
||
@Test | ||
fun deserialize() { | ||
server.enqueue(MockResponse().setBody("""{"name":"Bob"}""")) | ||
val user = service.deserialize().execute().body()!! | ||
assertEquals(User("Bob"), user) | ||
} | ||
|
||
@Test | ||
fun serialize() { | ||
server.enqueue(MockResponse()) | ||
service.serialize(User("Bob")).execute() | ||
val request = server.takeRequest() | ||
assertEquals("""{"name":"Bob"}""", request.body.readUtf8()) | ||
assertEquals("application/json; charset=UTF-8", request.headers["Content-Type"]) | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
...fit2/converter/kotlinx/serialization/json/KotlinxSerializationJsonConverterFactoryTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package retrofit2.converter.kotlinx.serialization.json | ||
|
||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.json.Json | ||
import okhttp3.mockwebserver.MockResponse | ||
import okhttp3.mockwebserver.MockWebServer | ||
import org.junit.Assert.assertEquals | ||
import org.junit.Before | ||
import org.junit.Rule | ||
import org.junit.Test | ||
import retrofit2.Call | ||
import retrofit2.Retrofit | ||
import retrofit2.http.Body | ||
import retrofit2.http.GET | ||
import retrofit2.http.POST | ||
|
||
class KotlinxSerializationJsonConverterFactoryTest { | ||
@get:Rule val server = MockWebServer() | ||
|
||
private lateinit var service: Service | ||
|
||
interface Service { | ||
@GET("/") fun deserialize(): Call<User> | ||
@POST("/") fun serialize(@Body user: User): Call<Void?> | ||
} | ||
|
||
@Serializable | ||
data class User(val name: String) | ||
|
||
@Before fun setUp() { | ||
val retrofit = Retrofit.Builder() | ||
.baseUrl(server.url("/")) | ||
.addConverterFactory(Json.asConverterFactory()) | ||
.build() | ||
service = retrofit.create(Service::class.java) | ||
} | ||
|
||
@Test fun deserialize() { | ||
server.enqueue(MockResponse().setBody("""{"name":"Bob"}""")) | ||
val user = service.deserialize().execute().body()!! | ||
assertEquals(User("Bob"), user) | ||
} | ||
|
||
@Test fun serialize() { | ||
server.enqueue(MockResponse()) | ||
service.serialize(User("Bob")).execute() | ||
val request = server.takeRequest() | ||
assertEquals("""{"name":"Bob"}""", request.body.readUtf8()) | ||
assertEquals("application/json; charset=UTF-8", request.headers["Content-Type"]) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters