Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
tech.pylons.lib.JsonModelSerializer.kt Maven / Gradle / Ivy
package tech.pylons.lib
import com.beust.klaxon.Json
import com.beust.klaxon.JsonArray
import com.beust.klaxon.JsonObject
import kotlin.reflect.KProperty1
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.memberProperties
object JsonModelSerializer {
fun serialize (mode : SerializationMode, obj: Any?) : String {
val jo = processObject(mode, obj)
return jo?.toJsonString(
prettyPrint = mode == SerializationMode.FOR_BROADCAST,
canonical = true
).orEmpty().replace("{}", "null")
// HACK! this is used to not serialize empty maps atm.
// TODO: write proper map handling so we don't need Bullshit here
}
private fun processObject (mode : SerializationMode, obj: Any?) : JsonObject? {
if (obj != null) {
val kClass = obj::class
val o = JsonObject()
kClass.memberProperties.forEach { prop ->
val json = prop.findAnnotation()
if (json != null) {
var value = prop.getter.call(obj)
if (prop.returnType == String::class.java) value = value.toString()
when (prop.returnType.classifier) {
// HACK: klaxon's serialization of byte values is actually broken!
// We have to do this b/c if we just set value w/o doing the Bullshit
// it'll be serialized as... an empty object. Thanks, klaxon!
Byte::class -> o[json.name] = (value as Byte).toInt()
Int::class -> {
val q = prop.findAnnotation()
val n = prop.findAnnotation()
if ((q != null || mode == SerializationMode.FOR_BROADCAST) && n == null)
o[json.name] = (value as Int).toString()
else o[json.name] = value
}
Long::class -> {
val q = prop.findAnnotation()
val n = prop.findAnnotation()
if ((q != null || mode == SerializationMode.FOR_BROADCAST) && n == null)
o[json.name] = (value as Long).toString()
else o[json.name] = value
}
Number::class -> o[json.name] = value
Float::class -> o[json.name] = value
Double::class -> o[json.name] = value
Boolean::class -> o[json.name] = value
String::class -> o[json.name] = value
else -> o[json.name] = handleComplexValues(mode, prop, value)
}
}
}
return o
}
else return null
}
private fun handleComplexValues (mode : SerializationMode, prop : KProperty1, value : Any?) : Any? {
return when {
value == null -> null
Regex("kotlin.Array<.*>").matches(prop.returnType.toString()) -> handleArrays(mode, prop, value)
Regex("kotlin.collections.List<.*>").matches(prop.returnType.toString()) -> handleLists(mode, prop, value)
Regex("kotlin.collections.Map<.*>").matches(prop.returnType.toString()) -> handleMaps(mode, prop, value)
else -> processObject(mode, value) // serialize nested object
}
}
private fun numeralArrayElement (mode: SerializationMode, it : T, q : QuotedJsonNumeral?, arr: JsonArray) {
if (q != null && (q.serializationMode == SerializationMode.ALL || q.serializationMode == mode))
arr.add(it.toString())
else arr.add(it)
}
private fun handleArrays (mode : SerializationMode, prop : KProperty1, value : Any?) : JsonArray<*>? {
if ((value as Array<*>).size == 0) return null
else {
val jsonArray = JsonArray()
val q = prop.findAnnotation()
when (prop.returnType.toString()) {
"kotlin.Array" -> (value as Array).forEach { jsonArray.add(it) }
"kotlin.Array" -> (value as Array).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.Array" -> (value as Array).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.Array" -> (value as Array).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.Array" -> (value as Array).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.Array" -> (value as Array).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.Array" -> (value as Array).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.Array" -> (value as Array).forEach { jsonArray.add(it) }
else -> value.forEach { jsonArray.add(processObject(mode, it)) }
}
return jsonArray
}
}
private fun handleLists (mode : SerializationMode, prop : KProperty1, value : Any?) : JsonArray<*>? {
if ((value as List<*>).size == 0) {
return if (prop.findAnnotation() != null) {
JsonArray()
} else {
null
}
}
else {
val jsonArray = JsonArray()
val q = prop.findAnnotation()
when (prop.returnType.toString()) {
"kotlin.collections.List" -> (value as List).forEach { jsonArray.add(it) }
"kotlin.collections.List" -> (value as List).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.collections.List" -> (value as List).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.collections.List" -> (value as List).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.collections.List" -> (value as List).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.collections.List" -> (value as List).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.collections.List" -> (value as List).forEach { numeralArrayElement(mode, it, q, jsonArray) }
"kotlin.collections.List" -> (value as List).forEach { jsonArray.add(it) }
else -> value.forEach { jsonArray.add(processObject(mode, it)) }
}
return jsonArray
}
}
private fun handleMaps(mode : SerializationMode, prop : KProperty1, value : Any?): JsonArray<*>? {
if ((value as Map).size == 0) return null
else {
val jsonArray = JsonArray()
val q = prop.findAnnotation()
when (prop.returnType.toString()) {
"kotlin.collections.Map" -> (value as Map).forEach {
val obj = JsonObject()
obj["Key"] = it.key
// broadcast has to be string format "1" while signing has to be number 1
obj["Value"] = if (mode == SerializationMode.FOR_BROADCAST) {
it.value.toString()
} else {
it.value
}
jsonArray.add(obj)
}
"kotlin.collections.Map" -> (value as Map).forEach {
val obj = JsonObject()
obj["Key"] = it.key
obj["Value"] = it.value
jsonArray.add(obj)
}
else -> value.forEach {
val obj = JsonObject()
obj["Key"] = it.key
obj["Value"] = if (q != null && (q.serializationMode == SerializationMode.ALL || q.serializationMode == mode)) {
it.value.toString()
} else {
it.value
}
jsonArray.add(obj)
}
}
return if (jsonArray.isNotEmpty()) {
jsonArray
} else {
// must return null for empty array
null
}
}
}
}