Last active
September 19, 2023 12:18
-
-
Save beigirad/05802ca153dfa178686063d004a70e0c to your computer and use it in GitHub Desktop.
Moshi Json Adapter for Koltinx Immutable List/Collection
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
package com.example | |
import com.squareup.moshi.JsonAdapter | |
import com.squareup.moshi.JsonAdapter.Factory | |
import com.squareup.moshi.JsonReader | |
import com.squareup.moshi.JsonWriter | |
import com.squareup.moshi.Types | |
import com.squareup.moshi.rawType | |
import kotlinx.collections.immutable.ImmutableList | |
/** | |
* A wrapper class that delegates adaption of type [T] (like [ImmutableList]) into [Delegate] (like [List]) | |
* | |
* inspired from https://github.com/square/moshi/issues/449 | |
* source: https://gist.github.com/beigirad/05802ca153dfa178686063d004a70e0c | |
*/ | |
class DelegatingAdapter<T, Delegate> private constructor( | |
private val delegateAdapter: JsonAdapter<Delegate>, | |
private val fromDelegate: (Delegate?) -> T?, | |
private val toDelegate: (T?) -> Delegate?, | |
) : JsonAdapter<T>() { | |
override fun fromJson(reader: JsonReader): T? { | |
val delegate: Delegate? = delegateAdapter.fromJson(reader) | |
return fromDelegate.invoke(delegate) | |
} | |
override fun toJson(writer: JsonWriter, value: T?) { | |
delegateAdapter.toJson(writer, toDelegate.invoke(value)) | |
} | |
companion object { | |
/** | |
* Creates a factory for [T] using the already-existing factory for [Delegate], | |
* and converting between [T] and [Delegate] using the `fromDelegate` and | |
* `toDelegate` arguments. | |
* | |
* todo: this factory is currently only supports parametrized types | |
*/ | |
fun <T, Delegate> factory( | |
delegatingType: Class<T>, | |
delegateType: Class<Delegate>, | |
fromDelegate: (Delegate?) -> T?, | |
toDelegate: (T?) -> Delegate?, | |
): Factory = Factory { incomingType, annotations, moshi -> | |
if (annotations.isNotEmpty()) return@Factory null | |
if (incomingType.rawType != delegatingType) return@Factory null | |
val delegateRawType = delegateType.rawType | |
val elementType = Types.collectionElementType(incomingType, delegateRawType) | |
val genericDelegateType = Types.newParameterizedType(delegateRawType, elementType) | |
val delegateAdapter = moshi.adapter<Delegate>(genericDelegateType) | |
DelegatingAdapter(delegateAdapter, fromDelegate, toDelegate) | |
} | |
} | |
} |
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
Moshi.Builder() | |
.add(DelegatingAdapter.factory(ImmutableList::class.java, List::class.java, { it?.toImmutableList() }, { it })) | |
.add(DelegatingAdapter.factory(ImmutableSet::class.java, Set::class.java, { it?.toImmutableSet() }, { it })) | |
.add(DelegatingAdapter.factory(ImmutableMap::class.java, Map::class.java, { it?.toImmutableMap() }, { it })) | |
.build() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment