Last active
September 18, 2021 12:26
-
-
Save jishindev/9fd8f0191225dc8f0d1f7a6f6f0511a1 to your computer and use it in GitHub Desktop.
Kotlin | Moshi Type converters and adapters for common use cases. Will be updated with new ones.
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
@Suppress("UNCHECKED_CAST") | |
class ArrayListAdapter<T>(private val adapter: JsonAdapter<T>) : JsonAdapter<ArrayList<T>>() { | |
@Throws(IOException::class) | |
override fun fromJson(reader: JsonReader): ArrayList<T>? { | |
val arrayList = arrayListOf<T>() | |
reader.beginArray() | |
while (reader.hasNext()) { | |
(adapter.fromJson(reader))?.let { arrayList.add(it) } | |
} | |
reader.endArray() | |
return arrayList | |
} | |
@Throws(IOException::class) | |
override fun toJson(writer: JsonWriter, value: ArrayList<T>?) { | |
value ?: return | |
writer.beginArray() | |
for (element in value) { | |
adapter.toJson(writer, element) | |
} | |
writer.endArray() | |
} | |
class Factory<T : Any> : JsonAdapter.Factory { | |
override fun create(type: Type, annotations: Set<Annotation>, moshi: Moshi): JsonAdapter<*>? { | |
val rawType = Types.getRawType(type) | |
if (annotations.isNotEmpty()) return null | |
return if (rawType == ArrayList::class.java) { | |
newListAdapter<T>(type, moshi).nullSafe() | |
} else null | |
} | |
private fun <T : Any> newListAdapter(type: Type, moshi: Moshi): JsonAdapter<ArrayList<T>> { | |
val elementType = collectionElementType(type, ArrayList::class.java) | |
val elementAdapter = moshi.adapter<T>(elementType) | |
return ArrayListAdapter(elementAdapter) | |
} | |
} | |
} |
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
/** | |
formats: yyyy-MM-dd, yyyy-MM-dd HH:mm:ss, HH:mm:ss etc | |
*/ | |
@Retention(AnnotationRetention.RUNTIME) | |
@JsonQualifier | |
internal annotation class JsonDateTimeFormat(val format: String) | |
class DateTimeAdapter(private val format: String) : JsonAdapter<Date?>() { | |
override fun fromJson(reader: JsonReader): Date? { | |
val string = reader.nextString() | |
return SimpleDateFormat(format, Locale.getDefault()).parse(string) | |
} | |
override fun toJson(writer: JsonWriter, value: Date?) { | |
writer.value(SimpleDateFormat(format, Locale.getDefault()).format(value)) | |
} | |
class Factory : JsonAdapter.Factory { | |
override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<Date?>? { | |
if (annotations.size <= 1 && type != Date::class.java) return null | |
val annotation = annotations.iterator().next() as? JsonDateTimeFormat ?: return null | |
val format = annotation.format | |
return DateTimeAdapter(format).nullSafe() | |
} | |
} | |
} |
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
class SafeEnumListAdapter<T : Enum<T>>(enumType: Class<T>) : JsonAdapter<List<T>>() { | |
private val nameStrings: Array<String> | |
private val constants: Array<T> | |
private val options: JsonReader.Options | |
init { | |
try { | |
constants = enumType.enumConstants | |
nameStrings = Array(constants.size) { | |
val constant = constants[it] | |
val annotation = enumType.getField(constant.name).getAnnotation(Json::class.java) | |
annotation?.name ?: constant.name | |
} | |
options = JsonReader.Options.of(*nameStrings) | |
} catch (e: NoSuchFieldException) { | |
throw AssertionError("Missing field in " + enumType.name, e) | |
} | |
} | |
@Throws(IOException::class) | |
override fun fromJson(reader: JsonReader): List<T> { | |
reader.beginArray() | |
val list = mutableListOf<T>() | |
while (reader.hasNext()) { | |
val index = reader.selectString(options) | |
if (index != -1) { | |
list += constants[index] | |
} else { | |
reader.skipValue() | |
} | |
} | |
reader.endArray() | |
return list | |
} | |
@Throws(IOException::class) | |
override fun toJson(writer: JsonWriter, value: List<T>?) { | |
if (value == null) { | |
throw IllegalArgumentException("Wrap in .nullSafe()") | |
} | |
writer.beginArray() | |
for (i in value.indices) { | |
writer.value(nameStrings[value[i].ordinal]) | |
} | |
writer.endArray() | |
} | |
} |
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
class UriAdapter : JsonAdapter<Uri>() { | |
companion object { | |
val FACTORY = Factory { type, _, _ -> | |
return@Factory if (type === Uri::class.java) { | |
UriAdapter() | |
} else { | |
null | |
} | |
} | |
} | |
@Throws(IOException::class) | |
override fun fromJson(reader: JsonReader): Uri { | |
return Uri.parse(reader.nextString()) | |
} | |
@Throws(IOException::class) | |
override fun toJson( | |
writer: JsonWriter, | |
value: Uri? | |
) { | |
writer.value(value?.toString()) | |
} | |
override fun toString(): String { | |
return "JsonAdapter(Uri)" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment