11package gr.indice.identity.utils
22
33import com.squareup.moshi.FromJson
4+ import com.squareup.moshi.JsonAdapter
5+ import com.squareup.moshi.JsonDataException
46import com.squareup.moshi.JsonReader
7+ import com.squareup.moshi.JsonWriter
58import com.squareup.moshi.Moshi
9+ import com.squareup.moshi.Types
610import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
711import gr.indice.identity.adapters.OffsetDateTimeAdapter
812import gr.indice.identity.adapters.UUIDAdapter
13+ import gr.indice.identity.utils.Serializer.moshiBuilder
14+ import java.lang.reflect.Type
15+ import java.math.BigDecimal
916
1017object Serializer {
1118
1219 @JvmStatic
1320 val moshiBuilder: Moshi .Builder = Moshi .Builder ()
21+ .add(SmartAnyAdapterFactory ())
1422 .add(KotlinJsonAdapterFactory ())
1523 .add(OffsetDateTimeAdapter ())
1624 .add(UUIDAdapter ())
17- .add(IntOrDoubleAdapter ())
1825 // .add(OffsetDateTimeAdapter())
1926 // .add(LocalDateTimeAdapter())
2027 // .add(LocalDateAdapter())
@@ -53,11 +60,88 @@ object Serializer {
5360 }
5461 }
5562
56- class IntOrDoubleAdapter {
57- @FromJson
58- fun fromJson (reader : JsonReader ): Number {
59- val num = reader.nextDouble()
60- return if (num % 1 == 0.0 ) num.toInt() else num
63+ class SmartAnyAdapterFactory : JsonAdapter .Factory {
64+ override fun create (type : Type , annotations : Set <Annotation >, moshi : Moshi ): JsonAdapter <* >? {
65+ val raw = Types .getRawType(type)
66+
67+ return when (raw) {
68+ Any ::class .java -> SmartNumberAnyAdapter ()
69+ else -> null
70+ }
71+ }
72+ }
73+
74+ class SmartNumberAnyAdapter () : JsonAdapter<Any>() {
75+ override fun fromJson (reader : JsonReader ): Any? {
76+ return when (reader.peek()) {
77+ JsonReader .Token .BEGIN_OBJECT -> {
78+ val map = mutableMapOf<String , Any ?>()
79+ reader.beginObject()
80+ while (reader.hasNext()) {
81+ map[reader.nextName()] = fromJson(reader)
82+ }
83+ reader.endObject()
84+ map
85+ }
86+
87+ JsonReader .Token .BEGIN_ARRAY -> {
88+ val list = mutableListOf<Any ?>()
89+ reader.beginArray()
90+ while (reader.hasNext()) {
91+ list.add(fromJson(reader))
92+ }
93+ reader.endArray()
94+ list
95+ }
96+
97+ JsonReader .Token .STRING -> reader.nextString()
98+ JsonReader .Token .BOOLEAN -> reader.nextBoolean()
99+ JsonReader .Token .NULL -> reader.nextNull()
100+ JsonReader .Token .NUMBER -> parseNumber(reader.nextString())
101+
102+ else -> throw JsonDataException (" Unexpected token ${reader.peek()} " )
103+ }
104+ }
105+
106+ override fun toJson (writer : JsonWriter , value : Any? ) {
107+ when (value) {
108+ null -> writer.nullValue()
109+ is Number -> writer.value(value)
110+ is Boolean -> writer.value(value)
111+ is String -> writer.value(value)
112+
113+ is List <* > -> {
114+ writer.beginArray()
115+ value.forEach { toJson(writer, it) }
116+ writer.endArray()
117+ }
118+
119+ is Map <* , * > -> {
120+ writer.beginObject()
121+ value.forEach { (k, v) ->
122+ writer.name(k.toString())
123+ toJson(writer, v)
124+ }
125+ writer.endObject()
126+ }
127+
128+ else -> throw JsonDataException (" Unsupported type ${value::class } " )
129+ }
130+ }
131+
132+ private fun parseNumber (raw : String ): Number {
133+ val dec = BigDecimal (raw)
134+
135+ return try {
136+ dec.intValueExact()
137+ } catch (_: Exception ) {
138+ try {
139+ dec.longValueExact()
140+ } catch (_: Exception ) {
141+ if (dec.scale() == 0 ) dec
142+ else dec
143+ }
144+ }
61145 }
62146 }
63- }
147+ }
0 commit comments