Skip to content

Instantly share code, notes, and snippets.

@smallufo
Created December 30, 2019 06:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smallufo/985db4719c5434a5f57f06b14011de78 to your computer and use it in GitHub Desktop.
Save smallufo/985db4719c5434a5f57f06b14011de78 to your computer and use it in GitHub Desktop.
package moshi
import com.squareup.moshi.*
interface IRunnable {
fun run()
}
class Cat : IRunnable {
override fun run() { println("cat running") }
}
class Dog : IRunnable {
override fun run() { println("dog running") }
}
interface IMapConverter<T> {
fun getMap(impl : T) : Map<String , String>
fun getImpl(map : Map<String , String>) : T?
}
class RunnableConverter : IMapConverter<IRunnable> {
private val key = "runnable"
override fun getMap(impl: IRunnable): Map<String, String> {
val value = when(impl) {
is Cat -> "C"
is Dog -> "D"
else -> throw RuntimeException("error")
}
return mapOf(key to value)
}
override fun getImpl(map: Map<String, String>): IRunnable? {
return map[key]?.let { value ->
when (value) {
"C" -> Cat()
"D" -> Dog()
else -> throw RuntimeException("error")
}
}
}
fun getAdapter() : JsonAdapter<IRunnable> {
return object : JsonAdapter<IRunnable>() {
@ToJson
override fun toJson(writer: JsonWriter, runnable: IRunnable?) {
runnable?.also { impl ->
writer.beginObject()
getMap(impl).forEach { (key , value) ->
writer.name(key).value(value)
}
writer.endObject()
}
}
@FromJson
override fun fromJson(reader: JsonReader): IRunnable? {
reader.beginObject()
val map = mutableMapOf<String , String>().apply {
while (reader.hasNext()) {
put(reader.nextName() , reader.nextString())
}
}
val result = getImpl(map)
reader.endObject()
return result
}
}
}
}
fun <T> IMapConverter<T>.toJsonAdapter() : JsonAdapter<T> {
return object : JsonAdapter<T>() {
@ToJson
override fun toJson(writer: JsonWriter, value: T?) {
value?.also { impl ->
writer.beginObject()
getMap(impl).forEach { (key , value) ->
writer.name(key).value(value)
}
writer.endObject()
}
}
@FromJson
override fun fromJson(reader: JsonReader): T? {
reader.beginObject()
val map = mutableMapOf<String , String>().apply {
while (reader.hasNext()) {
put(reader.nextName() , reader.nextString())
}
}
val result = getImpl(map)
reader.endObject()
return result
}
}
}
package moshi
import com.squareup.moshi.Moshi
import mu.KotlinLogging
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class MoshiTest {
private val logger = KotlinLogging.logger { }
@Test
fun testConverter1() {
val converter = RunnableConverter()
val moshi = Moshi.Builder()
.add(converter.getAdapter())
.build()
val adapter = moshi.adapter<IRunnable>(IRunnable::class.java)
adapter.toJson(Dog()).also { json ->
assertEquals("""{"runnable":"D"}""" , json)
adapter.fromJson(json).also { runnable ->
assertTrue(runnable is Dog)
}
}
}
// java.lang.IllegalArgumentException: No JsonAdapter for interface moshi.IRunnable (with no annotations)
@Test
fun testConverter2() {
val converter = RunnableConverter()
val moshi = Moshi.Builder()
.add(converter.toJsonAdapter())
.build()
val adapter = moshi.adapter<IRunnable>(IRunnable::class.java)
adapter.toJson(Dog()).also { json ->
logger.info("json of dog = {}", json)
assertEquals("""{"runnable":"D"}""" , json)
adapter.fromJson(json).also { runnable ->
assertTrue(runnable is Dog)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment