如何使Kotlin数据类的declaredMemberProperties保持定义顺序用于CSV导出
解决Kotlin数据类转CSV时保持字段定义顺序的问题
问题描述
Android应用中用多个数据类对应数据库表,需要把数据导出为CSV格式,但当前用declaredMemberProperties遍历属性时,字段会按字母顺序排序,没法保持数据类里的定义顺序。另外之前的方案还存在无法获取属性具体值的问题。
数据类示例:
data class Table1( @PrimaryKey(autoGenerate = true) var id: Int = 0, var dataA: String, var dataH: String, var dataB: String ) data class Table2( @PrimaryKey(autoGenerate = true) var id: Int = 0, var dataG: String, var dataC: String, var dataD: String )
当前实现的函数输出会是字母排序的结果(比如A;B;H;0;),但期望按数据类定义顺序输出(比如0;A;H;B;)。
解决方案
利用Kotlin数据类的primaryConstructor获取字段定义顺序——数据类主构造函数的参数顺序和类中字段定义顺序完全一致。遍历主构造函数参数,再映射到对应的成员属性取值,就能保持原有顺序。
修改后的函数实现:
fun datatableToStrings(tableDatasets: List<Any>): String { if (tableDatasets.isEmpty()) return "" val kClass = tableDatasets[0].javaClass.kotlin // 仅支持数据类,确保能获取主构造函数参数 require(kClass.isData) { "仅支持数据类转换" } val primaryConstructor = kClass.primaryConstructor ?: return "" val properties = primaryConstructor.parameters.mapNotNull { param -> kClass.declaredMemberProperties.find { it.name == param.name } } val bufferList = mutableListOf<StringBuilder>().apply { add(StringBuilder()) // 表头行 repeat(tableDatasets.size) { add(StringBuilder()) } // 数据行 } // 填充表头和数据 properties.forEach { prop -> // 添加表头 bufferList[0].append("${prop.name};") // 添加每行数据 tableDatasets.forEachIndexed { index, item -> val value = prop.get(item).toString() bufferList[index + 1].append("$value;") } } // 拼接所有行 return bufferList.joinToString(separator = "\n") { it.toString() } }
代码说明
- 数据类校验:先判断输入对象是否为数据类,确保能获取到主构造函数。
- 有序属性获取:通过
primaryConstructor.parameters拿到按定义顺序排列的参数,再映射为对应的成员属性。 - 高效字符串拼接:用
StringBuilder替代直接字符串拼接,提升性能。 - 顺序填充数据:按属性定义顺序依次填充表头和每行数据,保证输出顺序和数据类一致。
测试示例
调用函数:
Log.d("AAA", datatableToStrings(listOf(Table1(0, "A", "H", "B"))))
带表头的输出结果:
id;dataA;dataH;dataB; 0;A;H;B;
如果不需要表头,删除bufferList[0].append("${prop.name};")这一行,就能得到纯数据行:
0;A;H;B;
内容的提问来源于stack exchange,提问作者rescuemod
相关产品推荐
相关产品推荐

