基于JceStruct的泛型扩展函数设计
1. 基础设计
首先,我们假设JceStruct是后端序列化基类,所有响应数据都继承它。我将设计一个泛型扩展函数系统,支持动态反射将数据结构JSON化。
kotlin
// 假设的JceStruct基类
abstract class JceStruct {
// 假设JceStruct有一些基本属性和方法
}
// 示例数据类
class UserInfo : JceStruct() {
var userId: String = ""
var userName: String = ""
var age: Int = 0
var profile: UserProfile? = null
var friends: List<UserInfo> = emptyList()
}
class UserProfile : JceStruct() {
var avatar: String = ""
var bio: String = ""
var tags: List<String> = emptyList()
}
2. 核心扩展函数设计
2.1 基础JSON化扩展函数
kotlin
/**
* 将JceStruct及其子类转换为JSON字符串
* 支持嵌套对象和列表
*/
fun <T : JceStruct> T.toJsonString(
prettyPrint: Boolean = false,
excludeNullValues: Boolean = true
): String {
return toJson(excludeNullValues).toString(prettyPrint)
}
/**
* 将JceStruct及其子类转换为JSONObject
*/
fun <T : JceStruct> T.toJson(excludeNullValues: Boolean = true): JSONObject {
val jsonObject = JSONObject()
// 使用反射获取所有属性
this::class.members
.filterIsInstance<KProperty1<Any, *>>()
.forEach { property ->
try {
val value = property.get(this)
val propertyName = property.name
// 根据excludeNullValues决定是否排除null值
if (!excludeNullValues || value != null) {
when (value) {
is JceStruct -> {
// 递归处理嵌套的JceStruct对象
jsonObject.put(propertyName, value.toJson(excludeNullValues))
}
is List<*> -> {
// 处理列表
val jsonArray = JSONArray()
value.forEach { item ->
when (item) {
is JceStruct -> jsonArray.put(item.toJson(excludeNullValues))
else -> jsonArray.put(item)
}
}
jsonObject.put(propertyName, jsonArray)
}
is Map<*, *> -> {
// 处理Map
val jsonMap = JSONObject()
value.forEach { (key, mapValue) ->
when (mapValue) {
is JceStruct -> jsonMap.put(key.toString(), mapValue.toJson(excludeNullValues))
else -> jsonMap.put(key.toString(), mapValue)
}
}
jsonObject.put(propertyName, jsonMap)
}
else -> {
// 处理基本类型
jsonObject.put(propertyName, value)
}
}
}
} catch (e: Exception) {
// 忽略无法访问的属性
KLog.w("JceStructExtension", "Failed to serialize property: ${property.name}", e)
}
}
return jsonObject
}
2.2 高级扩展函数
kotlin
/**
* 将JceStruct转换为Map
*/
fun <T : JceStruct> T.toMap(
excludeNullValues: Boolean = true,
deep: Boolean = true
): Map<String, Any?> {
return if (deep) {
toJson(excludeNullValues).toMap()
} else {
val map = mutableMapOf<String, Any?>()
this::class.members
.filterIsInstance<KProperty1<Any, *>>()
.forEach { property ->
try {
val value = property.get(this)
if (!excludeNullValues || value != null) {
map[property.name] = value
}
} catch (e: Exception) {
KLog.w("JceStructExtension", "Failed to get property: ${property.name}", e)
}
}
map
}
}
/**
* 将JceStruct转换为特定类型的Map
*/
inline fun <reified K, reified V> <T : JceStruct> T.toTypedMap(
excludeNullValues: Boolean = true,
keyTransform: (String) -> K = { it as K },
valueTransform: (Any?) -> V = { it as V }
): Map<K, V> {
return toMap(excludeNullValues).mapKeys { (key, _) -> keyTransform(key) }
.mapValues { (_, value) -> valueTransform(value) }
}
/**
* 从JSON字符串创建JceStruct实例
*/
inline fun <reified T : JceStruct> String.toJceStruct(): T? {
return try {
val jsonObject = JSONObject(this)
jsonObject.toJceStruct<T>()
} catch (e: Exception) {
KLog.e("JceStructExtension", "Failed to parse JSON to JceStruct", e)
null
}
}
/**
* 从JSONObject创建JceStruct实例
*/
inline fun <reified T : JceStruct> JSONObject.toJceStruct(): T? {
return try {
val instance = T::class.createInstance()
this.keys().forEach { key ->
val value = this.opt(key)
val property = T::class.members
.filterIsInstance<KMutableProperty1<Any, *>>()
.find { it.name == key }
property?.let {
try {
when (val propValue = value) {
is JSONObject -> {
// 处理嵌套对象
val nestedValue = propValue.toJceStruct<JceStruct>()
it.setter.call(instance, nestedValue)
}
is JSONArray -> {
// 处理数组
val list = mutableListOf<Any?>()
for (i in 0 until propValue.length()) {
val item = propValue.opt(i)
when (item) {
is JSONObject -> {
val nestedItem = item.toJceStruct<JceStruct>()
list.add(nestedItem)
}
else -> list.add(item)
}
}
it.setter.call(instance, list)
}
else -> {
it.setter.call(instance, propValue)
}
}
} catch (e: Exception) {
KLog.w("JceStructExtension", "Failed to set property: $key", e)
}
}
}
instance
} catch (e: Exception) {
KLog.e("JceStructExtension", "Failed to create JceStruct from JSON", e)
null
}
}
3. 集合扩展函数
kotlin
/**
* 将JceStruct列表转换为JSON数组字符串
*/
fun <T : JceStruct> List<T>.toJsonString(
prettyPrint: Boolean = false,
excludeNullValues: Boolean = true
): String {
val jsonArray = JSONArray()
this.forEach { item ->
jsonArray.put(item.toJson(excludeNullValues))
}
return if (prettyPrint) {
jsonArray.toString(2)
} else {
jsonArray.toString()
}
}
/**
* 将JceStruct列表转换为JSONArray
*/
fun <T : JceStruct> List<T>.toJsonArray(excludeNullValues: Boolean = true): JSONArray {
val jsonArray = JSONArray()
this.forEach { item ->
jsonArray.put(item.toJson(excludeNullValues))
}
return jsonArray
}
/**
* 从JSON数组字符串创建JceStruct列表
*/
inline fun <reified T : JceStruct> String.toJceStructList(): List<T> {
return try {
val jsonArray = JSONArray(this)
jsonArray.toJceStructList<T>()
} catch (e: Exception) {
KLog.e("JceStructExtension", "Failed to parse JSON array to JceStruct list", e)
emptyList()
}
}
/**
* 从JSONArray创建JceStruct列表
*/
inline fun <reified T : JceStruct> JSONArray.toJceStructList(): List<T> {
val list = mutableListOf<T>()
for (i in 0 until this.length()) {
val item = this.opt(i)
when (item) {
is JSONObject -> {
val jceStruct = item.toJceStruct<T>()
jceStruct?.let { list.add(it) }
}
else -> KLog.w("JceStructExtension", "Item at index $i is not a JSONObject")
}
}
return list
}
4. 高级功能扩展
kotlin
/**
* 比较两个JceStruct对象的差异
*/
fun <T : JceStruct> T.diffWith(other: T): JSONObject {
val diff = JSONObject()
this::class.members
.filterIsInstance<KProperty1<Any, *>>()
.forEach { property ->
try {
val thisValue = property.get(this)
val otherValue = property.get(other)
if (thisValue != otherValue) {
val propertyDiff = JSONObject()
propertyDiff.put("old", thisValue)
propertyDiff.put("new", otherValue)
diff.put(property.name, propertyDiff)
}
} catch (e: Exception) {
KLog.w("JceStructExtension", "Failed to compare property: ${property.name}", e)
}
}
return diff
}
/**
* 合并两个JceStruct对象
*/
fun <T : JceStruct> T.mergeWith(other: T, overwrite: Boolean = true): T {
try {
val result = this::class.createInstance()
this::class.members
.filterIsInstance<KMutableProperty1<Any, *>>()
.forEach { property ->
try {
val thisValue = property.get(this)
val otherValue = property.get(other)
when {
otherValue != null && overwrite -> {
property.setter.call(result, otherValue)
}
thisValue != null -> {
property.setter.call(result, thisValue)
}
otherValue != null -> {
property.setter.call(result, otherValue)
}
}
} catch (e: Exception) {
KLog.w("JceStructExtension", "Failed to merge property: ${property.name}", e)
}
}
@Suppress("UNCHECKED_CAST")
return result as T
} catch (e: Exception) {
KLog.e("JceStructExtension", "Failed to merge JceStruct objects", e)
return this
}
}
/**
* 深度克隆JceStruct对象
*/
fun <T : JceStruct> T.deepClone(): T {
return this.toJsonString().toJceStruct<T>() ?: this
}
5. 使用示例
kotlin
// 创建测试数据
val userProfile = UserProfile().apply {
avatar = "https://example.com/avatar.jpg"
bio = "Software Developer"
tags = listOf("Kotlin", "Android", "iOS")
}
val userInfo = UserInfo().apply {
userId = "12345"
userName = "John Doe"
age = 30
profile = userProfile
friends = listOf(
UserInfo().apply {
userId = "67890"
userName = "Jane Smith"
age = 28
}
)
}
// 转换为JSON字符串
val jsonString = userInfo.toJsonString(prettyPrint = true)
println(jsonString)
// 转换为JSONObject
val jsonObject = userInfo.toJson()
println(jsonObject.toString())
// 转换为Map
val map = userInfo.toMap()
println(map)
// 从JSON字符串创建对象
val newUserInfo = jsonString.toJceStruct<UserInfo>()
println(newUserInfo?.userName)
// 处理列表
val userList = listOf(userInfo, newUserInfo ?: userInfo)
val listJsonString = userList.toJsonString(prettyPrint = true)
println(listJsonString)
// 比较差异
val diff = userInfo.diffWith(newUserInfo ?: userInfo)
println(diff.toString())
// 合并对象
val mergedUser = userInfo.mergeWith(newUserInfo ?: userInfo)
println(mergedUser.userName)
// 深度克隆
val clonedUser = userInfo.deepClone()
clonedUser.userName = "Cloned User"
println(userInfo.userName) // 原对象不变
println(clonedUser.userName) // 克隆对象已修改
6. 性能优化考虑
kotlin
/**
* 缓存反射结果以提高性能
*/
object JceStructReflectionCache {
private val propertyCache = mutableMapOf<KClass<*>, List<KProperty1<Any, *>>>()
private val mutablePropertyCache = mutableMapOf<KClass<*>, List<KMutableProperty1<Any, *>>>()
fun getProperties(clazz: KClass<*>): List<KProperty1<Any, *>> {
return propertyCache.getOrPut(clazz) {
clazz.members.filterIsInstance<KProperty1<Any, *>>()
}
}
fun getMutableProperties(clazz: KClass<*>): List<KMutableProperty1<Any, *>> {
return mutablePropertyCache.getOrPut(clazz) {
clazz.members.filterIsInstance<KMutableProperty1<Any, *>>()
}
}
}
// 使用缓存优化后的toJson方法
fun <T : JceStruct> T.toJsonOptimized(excludeNullValues: Boolean = true): JSONObject {
val jsonObject = JSONObject()
// 使用缓存的反射结果
JceStructReflectionCache.getProperties(this::class)
.forEach { property ->
try {
val value = property.get(this)
val propertyName = property.name
if (!excludeNullValues || value != null) {
when (value) {
is JceStruct -> {
jsonObject.put(propertyName, value.toJsonOptimized(excludeNullValues))
}
is List<*> -> {
val jsonArray = JSONArray()
value.forEach { item ->
when (item) {
is JceStruct -> jsonArray.put(item.toJsonOptimized(excludeNullValues))
else -> jsonArray.put(item)
}
}
jsonObject.put(propertyName, jsonArray)
}
else -> {
jsonObject.put(propertyName, value)
}
}
}
} catch (e: Exception) {
KLog.w("JceStructExtension", "Failed to serialize property: ${property.name}", e)
}
}
return jsonObject
}
7. 总结
这个设计提供了以下功能:
- 基础JSON转换:将JceStruct及其子类转换为JSON字符串和JSONObject
- 嵌套支持:自动处理嵌套的JceStruct对象和列表
- 反向转换:从JSON字符串和JSONObject创建JceStruct实例
- 集合支持:处理JceStruct列表的JSON转换
- 高级功能:对象比较、合并、深度克隆等
- 性能优化:使用反射缓存提高性能
这种设计充分利用了Kotlin的泛型、扩展函数和反射特性,为JceStruct及其子类提供了强大的JSON序列化和反序列化能力,同时保持了类型安全和易用性。