1
+ package com.enginebai.base.extensions
2
+
3
+ import com.google.gson.*
4
+ import com.google.gson.annotations.SerializedName
5
+ import retrofit2.Converter
6
+ import retrofit2.Retrofit
7
+ import timber.log.Timber
8
+ import java.lang.reflect.Type
9
+
10
+ /* *
11
+ * Enable to serialize enum with Gson @SerializedName annotation to Retrofit HTTP query string.
12
+ *
13
+ * Example:
14
+ * enum class MediaType {
15
+ * @SerializedName("image-jpeg")
16
+ * IMAGE_JPG,
17
+ * @SerializedName("video-mp4")
18
+ * VIDEO_MP4
19
+ * }
20
+ *
21
+ * interface ApiService {
22
+ * @GET
23
+ * fun getMediaList(@Query("type") mediaType: MediaType): List<Media>
24
+ * }
25
+ *
26
+ * val mediaList = apiService.getMediaList(MediaType.IMAGE_JPG)
27
+ *
28
+ * The actual HTTP request will be GET /medias?type=image-jpeg
29
+ */
30
+ object EnumGsonSerializedNameConverterFactory : Converter.Factory() {
31
+ override fun stringConverter (
32
+ type : Type ,
33
+ annotations : Array <out Annotation >,
34
+ retrofit : Retrofit
35
+ ): Converter <* , String >? {
36
+ if (type is Class <* > && type.isEnum) {
37
+ return Converter <Any ?, String > { value -> getSerializedNameValue(value as Enum <* >) }
38
+ }
39
+ return null
40
+ }
41
+
42
+ private fun <E : Enum <* >> getSerializedNameValue (e : E ): String {
43
+ val exception = IllegalStateException (
44
+ " You might miss the Gson @SerializedName annotation for " +
45
+ " your enum class $e that is used for Retrofit request/response"
46
+ )
47
+ return e.javaClass.getField(e.name).getAnnotation(SerializedName ::class .java)?.value
48
+ ? : throw exception
49
+ }
50
+ }
51
+
52
+ object EnumHasValueConverterFactory: Converter.Factory() {
53
+ override fun stringConverter (
54
+ type : Type ,
55
+ annotations : Array <out Annotation >,
56
+ retrofit : Retrofit
57
+ ): Converter <* , String >? {
58
+ if (type is Class <* > && type.isEnum && type.interfaces.contains(EnumHasValue ::class .java)) {
59
+ return Converter <Any ?, String > { value -> (value as EnumHasValue ).value }
60
+ }
61
+ return null
62
+ }
63
+ }
64
+
65
+ // source: https://stackoverflow.com/a/45561053/2279285
66
+ interface EnumHasValue {
67
+ val value: String
68
+ }
69
+
70
+ class EnumHasValueJsonAdapter <T > : JsonSerializer <T >, JsonDeserializer <T > where T : EnumHasValue {
71
+ override fun serialize (
72
+ src : T ,
73
+ typeOfSrc : Type ? ,
74
+ context : JsonSerializationContext ?
75
+ ): JsonElement {
76
+ return JsonPrimitive (src.value)
77
+ }
78
+
79
+ override fun deserialize (
80
+ json : JsonElement ,
81
+ typeOfT : Type ? ,
82
+ context : JsonDeserializationContext ?
83
+ ): T ? {
84
+ val parsedValue = (typeOfT as Class <T >).enumConstants?.associateBy { it.value }?.get(json.asString)
85
+ parsedValue ? : kotlin.run { Timber .w(" Can not deserialize value ${json.asString} to $typeOfT " ) }
86
+ return parsedValue
87
+ }
88
+
89
+ }
0 commit comments