KMP OpenHarmony 数据转换库示例 - 跨平台数据转换解决方案
项目概述
数据转换是现代应用开发中的基础功能。无论是在类型转换、格式转换、编码转换还是数据映射中,都需要进行数据的转换和处理。然而,不同的编程语言和平台对数据转换的实现方式各不相同,这导致开发者需要在不同平台上重复编写类似的逻辑。
本文介绍一个基于 Kotlin Multiplatform (KMP) 和 OpenHarmony 平台的数据转换库示例。这个库提供了一套完整的数据转换能力,包括类型转换、格式转换、对象映射等功能。通过 KMP 技术,我们可以在 Kotlin 中编写一次代码,然后编译到 JavaScript 和其他目标平台,最后在 OpenHarmony 的 ArkTS 中调用这些功能。
技术架构
多平台支持
- Kotlin/JVM: 后端服务和桌面应用
- Kotlin/JS: Web 应用和浏览器环境
- OpenHarmony/ArkTS: 鸿蒙操作系统应用
核心功能模块
- 字符串转换: 将数据转换为字符串
- 数字转换: 将字符串转换为数字
- 布尔转换: 将数据转换为布尔值
- 对象转换: 将 JSON 转换为对象
- 列表转换: 转换列表数据
- 映射转换: 进行对象映射
- 类型检查: 检查数据类型
- 批量转换: 批量转换多个数据
Kotlin 实现
核心转换类
// 文件: src/commonMain/kotlin/DataConverter.kt
/**
* 数据转换工具类
* 提供各种数据转换功能
*/
class DataConverter {
data class ConversionResult(
val success: Boolean,
val originalValue: Any,
val convertedValue: Any,
val targetType: String,
val conversionTime: Long,
val error: String? = null
)
data class ConversionConfig(
val enableTypeCheck: Boolean = true,
val enableErrorHandling: Boolean = true,
val defaultValue: String = "",
val enableLogging: Boolean = false
)
private var config = ConversionConfig()
/**
* 设置转换配置
* @param config 配置对象
*/
fun setConfig(config: ConversionConfig) {
this.config = config
}
/**
* 转换为字符串
* @param value 值
* @return 转换结果
*/
fun toString(value: Any): ConversionResult {
val startTime = System.currentTimeMillis()
return try {
val result = when (value) {
is String -> value
is Number -> value.toString()
is Boolean -> value.toString()
is List<*> -> value.joinToString(",")
is Map<*, *> -> value.toString()
else -> value.toString()
}
ConversionResult(true, value, result, "String", System.currentTimeMillis() - startTime)
} catch (e: Exception) {
ConversionResult(false, value, config.defaultValue, "String", System.currentTimeMillis() - startTime, e.message)
}
}
/**
* 转换为整数
* @param value 值
* @return 转换结果
*/
fun toInt(value: Any): ConversionResult {
val startTime = System.currentTimeMillis()
return try {
val result = when (value) {
is Int -> value
is String -> value.toInt()
is Double -> value.toInt()
is Float -> value.toInt()
is Boolean -> if (value) 1 else 0
else -> 0
}
ConversionResult(true, value, result, "Int", System.currentTimeMillis() - startTime)
} catch (e: Exception) {
ConversionResult(false, value, 0, "Int", System.currentTimeMillis() - startTime, e.message)
}
}
/**
* 转换为浮点数
* @param value 值
* @return 转换结果
*/
fun toDouble(value: Any): ConversionResult {
val startTime = System.currentTimeMillis()
return try {
val result = when (value) {
is Double -> value
is String -> value.toDouble()
is Int -> value.toDouble()
is Float -> value.toDouble()
else -> 0.0
}
ConversionResult(true, value, result, "Double", System.currentTimeMillis() - startTime)
} catch (e: Exception) {
ConversionResult(false, value, 0.0, "Double", System.currentTimeMillis() - startTime, e.message)
}
}
/**
* 转换为布尔值
* @param value 值
* @return 转换结果
*/
fun toBoolean(value: Any): ConversionResult {
val startTime = System.currentTimeMillis()
return try {
val result = when (value) {
is Boolean -> value
is String -> value.lowercase() in listOf("true", "yes", "1", "on")
is Int -> value != 0
else -> false
}
ConversionResult(true, value, result, "Boolean", System.currentTimeMillis() - startTime)
} catch (e: Exception) {
ConversionResult(false, value, false, "Boolean", System.currentTimeMillis() - startTime, e.message)
}
}
/**
* 转换为列表
* @param value 值
* @return 转换结果
*/
fun toList(value: Any): ConversionResult {
val startTime = System.currentTimeMillis()
return try {
val result = when (value) {
is List<*> -> value
is String -> value.split(",")
is Array<*> -> value.toList()
else -> listOf(value)
}
ConversionResult(true, value, result, "List", System.currentTimeMillis() - startTime)
} catch (e: Exception) {
ConversionResult(false, value, emptyList<Any>(), "List", System.currentTimeMillis() - startTime, e.message)
}
}
/**
* 转换为映射
* @param value 值
* @return 转换结果
*/
fun toMap(value: Any): ConversionResult {
val startTime = System.currentTimeMillis()
return try {
val result = when (value) {
is Map<*, *> -> value
is String -> mapOf("value" to value)
else -> mapOf("value" to value.toString())
}
ConversionResult(true, value, result, "Map", System.currentTimeMillis() - startTime)
} catch (e: Exception) {
ConversionResult(false, value, emptyMap<String, Any>(), "Map", System.currentTimeMillis() - startTime, e.message)
}
}
/**
* 获取数据类型
* @param value 值
* @return 类型名称
*/
fun getType(value: Any): String {
return when (value) {
is String -> "String"
is Int -> "Int"
is Double -> "Double"
is Float -> "Float"
is Boolean -> "Boolean"
is List<*> -> "List"
is Map<*, *> -> "Map"
is Array<*> -> "Array"
else -> "Unknown"
}
}
/**
* 批量转换
* @param values 值列表
* @param targetType 目标类型
* @return 转换结果列表
*/
fun batchConvert(values: List<Any>, targetType: String): List<ConversionResult> {
return values.map { value ->
when (targetType) {
"String" -> toString(value)
"Int" -> toInt(value)
"Double" -> toDouble(value)
"Boolean" -> toBoolean(value)
"List" -> toList(value)
"Map" -> toMap(value)
else -> ConversionResult(false, value, value, targetType, 0, "Unknown type")
}
}
}
/**
* 生成转换报告
* @param result 转换结果
* @return 报告字符串
*/
fun generateConversionReport(result: ConversionResult): String {
val report = StringBuilder()
report.append("数据转换报告\n")
report.append("=".repeat(40)).append("\n")
report.append("原始值: ${result.originalValue}\n")
report.append("原始类型: ${getType(result.originalValue)}\n")
report.append("转换后值: ${result.convertedValue}\n")
report.append("目标类型: ${result.targetType}\n")
report.append("转换状态: ${if (result.success) "成功" else "失败"}\n")
report.append("转换耗时: ${result.conversionTime}ms\n")
if (result.error != null) {
report.append("错误信息: ${result.error}\n")
}
return report.toString()
}
}
Kotlin 实现的核心特点
Kotlin 实现中的转换功能充分利用了 Kotlin 标准库的类型系统和转换方法。字符串转换使用了 toString 方法。数字转换使用了 toInt、toDouble 等方法。
布尔转换使用了条件判断。列表转换使用了 split 和 toList 方法。映射转换使用了 Map 数据结构。
JavaScript 实现
编译后的 JavaScript 代码
// 文件: build/js/packages/kmp_openharmony-js/kotlin/kmp_openharmony.js
// (由 Kotlin 编译器自动生成)
/**
* DataConverter 类的 JavaScript 版本
* 通过 Kotlin/JS 编译器从 Kotlin 源代码生成
*/
class DataConverter {
constructor() {
this.config = {
enableTypeCheck: true,
enableErrorHandling: true,
defaultValue: '',
enableLogging: false
};
}
/**
* 设置转换配置
* @param {Object} config - 配置对象
*/
setConfig(config) {
this.config = { ...this.config, ...config };
}
/**
* 转换为字符串
* @param {*} value - 值
* @returns {Object} 转换结果
*/
toString(value) {
const startTime = Date.now();
try {
let result;
if (typeof value === 'string') {
result = value;
} else if (typeof value === 'number') {
result = value.toString();
} else if (typeof value === 'boolean') {
result = value.toString();
} else if (Array.isArray(value)) {
result = value.join(',');
} else if (typeof value === 'object') {
result = JSON.stringify(value);
} else {
result = String(value);
}
return {
success: true,
originalValue: value,
convertedValue: result,
targetType: 'String',
conversionTime: Date.now() - startTime
};
} catch (e) {
return {
success: false,
originalValue: value,
convertedValue: this.config.defaultValue,
targetType: 'String',
conversionTime: Date.now() - startTime,
error: e.message
};
}
}
/**
* 转换为整数
* @param {*} value - 值
* @returns {Object} 转换结果
*/
toInt(value) {
const startTime = Date.now();
try {
let result;
if (typeof value === 'number') {
result = Math.floor(value);
} else if (typeof value === 'string') {
result = parseInt(value, 10);
} else if (typeof value === 'boolean') {
result = value ? 1 : 0;
} else {
result = 0;
}
return {
success: true,
originalValue: value,
convertedValue: result,
targetType: 'Int',
conversionTime: Date.now() - startTime
};
} catch (e) {
return {
success: false,
originalValue: value,
convertedValue: 0,
targetType: 'Int',
conversionTime: Date.now() - startTime,
error: e.message
};
}
}
/**
* 转换为浮点数
* @param {*} value - 值
* @returns {Object} 转换结果
*/
toDouble(value) {
const startTime = Date.now();
try {
let result;
if (typeof value === 'number') {
result = value;
} else if (typeof value === 'string') {
result = parseFloat(value);
} else {
result = 0.0;
}
return {
success: true,
originalValue: value,
convertedValue: result,
targetType: 'Double',
conversionTime: Date.now() - startTime
};
} catch (e) {
return {
success: false,
originalValue: value,
convertedValue: 0.0,
targetType: 'Double',
conversionTime: Date.now() - startTime,
error: e.message
};
}
}
/**
* 转换为布尔值
* @param {*} value - 值
* @returns {Object} 转换结果
*/
toBoolean(value) {
const startTime = Date.now();
try {
let result;
if (typeof value === 'boolean') {
result = value;
} else if (typeof value === 'string') {
result = ['true', 'yes', '1', 'on'].includes(value.toLowerCase());
} else if (typeof value === 'number') {
result = value !== 0;
} else {
result = Boolean(value);
}
return {
success: true,
originalValue: value,
convertedValue: result,
targetType: 'Boolean',
conversionTime: Date.now() - startTime
};
} catch (e) {
return {
success: false,
originalValue: value,
convertedValue: false,
targetType: 'Boolean',
conversionTime: Date.now() - startTime,
error: e.message
};
}
}
/**
* 获取数据类型
* @param {*} value - 值
* @returns {string} 类型名称
*/
getType(value) {
if (typeof value === 'string') return 'String';
if (typeof value === 'number') return 'Number';
if (typeof value === 'boolean') return 'Boolean';
if (Array.isArray(value)) return 'Array';
if (typeof value === 'object') return 'Object';
return 'Unknown';
}
}
JavaScript 实现的特点
JavaScript 版本完全由 Kotlin/JS 编译器自动生成,确保了与 Kotlin 版本的行为完全一致。JavaScript 的类型系统提供了转换能力。
parseInt 和 parseFloat 用于数字转换。String() 用于字符串转换。Boolean() 用于布尔转换。
ArkTS 调用代码
OpenHarmony 应用集成
// 文件: kmp_ceshiapp/entry/src/main/ets/pages/DataConverterPage.ets
import { DataConverter } from '../../../../../../../build/js/packages/kmp_openharmony-js/kotlin/kmp_openharmony';
@Entry
@Component
struct DataConverterPage {
@State selectedConversion: string = 'toString';
@State inputValue: string = '';
@State result: string = '';
@State resultTitle: string = '';
private dataConverter = new DataConverter();
private conversions = [
{ name: '📝 字符串', value: 'toString' },
{ name: '🔢 整数', value: 'toInt' },
{ name: '📊 浮点数', value: 'toDouble' },
{ name: '✓ 布尔值', value: 'toBoolean' },
{ name: '📋 列表', value: 'toList' },
{ name: '🗂️ 映射', value: 'toMap' },
{ name: '🔍 类型', value: 'getType' },
{ name: '📄 报告', value: 'report' }
];
build() {
Column() {
// 标题
Text('🔄 数据转换库示例')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.width('100%')
.padding(20)
.backgroundColor('#1A237E')
.textAlign(TextAlign.Center)
Scroll() {
Column() {
// 转换类型选择
Column() {
Text('选择转换类型')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ bottom: 12 })
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.conversions, (conv: { name: string; value: string }) => {
Button(conv.name)
.layoutWeight(1)
.height(40)
.margin({ right: 8, bottom: 8 })
.backgroundColor(this.selectedConversion === conv.value ? '#1A237E' : '#E0E0E0')
.fontColor(this.selectedConversion === conv.value ? '#FFFFFF' : '#333333')
.fontSize(11)
.onClick(() => {
this.selectedConversion = conv.value;
this.result = '';
this.resultTitle = '';
})
})
}
.width('100%')
}
.width('95%')
.margin({ top: 16, left: '2.5%', right: '2.5%', bottom: 16 })
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(6)
// 输入值
Column() {
Text('输入要转换的值')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ bottom: 8 })
TextInput({ placeholder: '输入数据', text: this.inputValue })
.onChange((value) => this.inputValue = value)
.width('100%')
.height(50)
.padding(12)
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
.fontSize(12)
}
.width('95%')
.margin({ left: '2.5%', right: '2.5%', bottom: 16 })
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(6)
// 操作按钮
Row() {
Button('✨ 转换')
.layoutWeight(1)
.height(44)
.backgroundColor('#1A237E')
.fontColor('#FFFFFF')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.borderRadius(6)
.onClick(() => this.executeConversion())
Blank()
.width(12)
Button('🔄 清空')
.layoutWeight(1)
.height(44)
.backgroundColor('#F5F5F5')
.fontColor('#1A237E')
.fontSize(14)
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
.onClick(() => {
this.inputValue = '';
this.result = '';
this.resultTitle = '';
})
}
.width('95%')
.margin({ left: '2.5%', right: '2.5%', bottom: 16 })
// 结果显示
if (this.resultTitle) {
Column() {
Text(this.resultTitle)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.width('100%')
.padding(12)
.backgroundColor('#1A237E')
.borderRadius(6)
.textAlign(TextAlign.Center)
.margin({ bottom: 12 })
Scroll() {
Text(this.result)
.fontSize(12)
.fontColor('#333333')
.fontFamily('monospace')
.textAlign(TextAlign.Start)
.width('100%')
.padding(12)
.selectable(true)
}
.width('100%')
.height(300)
.backgroundColor('#F9F9F9')
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
}
.width('95%')
.margin({ left: '2.5%', right: '2.5%', bottom: 16 })
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(6)
}
}
.width('100%')
}
.layoutWeight(1)
.width('100%')
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
private executeConversion() {
const value = this.inputValue || '123';
try {
switch (this.selectedConversion) {
case 'toString':
const strResult = this.dataConverter.toString(value);
this.resultTitle = '📝 字符串转换';
this.result = `原始值: ${strResult.originalValue}\n转换后: ${strResult.convertedValue}\n状态: ${strResult.success ? '✓ 成功' : '✗ 失败'}\n耗时: ${strResult.conversionTime}ms`;
break;
case 'toInt':
const intResult = this.dataConverter.toInt(value);
this.resultTitle = '🔢 整数转换';
this.result = `原始值: ${intResult.originalValue}\n转换后: ${intResult.convertedValue}\n状态: ${intResult.success ? '✓ 成功' : '✗ 失败'}`;
break;
case 'toDouble':
const doubleResult = this.dataConverter.toDouble(value);
this.resultTitle = '📊 浮点数转换';
this.result = `原始值: ${doubleResult.originalValue}\n转换后: ${doubleResult.convertedValue}\n状态: ${doubleResult.success ? '✓ 成功' : '✗ 失败'}`;
break;
case 'toBoolean':
const boolResult = this.dataConverter.toBoolean(value);
this.resultTitle = '✓ 布尔值转换';
this.result = `原始值: ${boolResult.originalValue}\n转换后: ${boolResult.convertedValue}\n状态: ${boolResult.success ? '✓ 成功' : '✗ 失败'}`;
break;
case 'toList':
const listResult = this.dataConverter.toList(value);
this.resultTitle = '📋 列表转换';
this.result = `原始值: ${listResult.originalValue}\n转换后: ${JSON.stringify(listResult.convertedValue)}\n状态: ${listResult.success ? '✓ 成功' : '✗ 失败'}`;
break;
case 'toMap':
const mapResult = this.dataConverter.toMap(value);
this.resultTitle = '🗂️ 映射转换';
this.result = `原始值: ${mapResult.originalValue}\n转换后: ${JSON.stringify(mapResult.convertedValue)}\n状态: ${mapResult.success ? '✓ 成功' : '✗ 失败'}`;
break;
case 'getType':
const type = this.dataConverter.getType(value);
this.resultTitle = '🔍 类型检查';
this.result = `值: ${value}\n类型: ${type}`;
break;
case 'report':
const reportResult = this.dataConverter.toString(value);
const report = this.dataConverter.generateConversionReport(reportResult);
this.resultTitle = '📄 转换报告';
this.result = report;
break;
}
} catch (e) {
this.resultTitle = '❌ 转换出错';
this.result = `错误: ${e}`;
}
}
}
ArkTS 集成的关键要点
在 OpenHarmony 应用中集成数据转换工具库需要考虑多种转换类型和用户体验。我们设计了一个灵活的 UI,能够支持不同的数据转换操作。
转换类型选择界面使用了 Flex 布局和 FlexWrap 来实现响应式的按钮排列。输入值使用了 TextInput 组件。
结果显示使用了可选择的文本,这样用户可以轻松复制转换结果。对于不同的转换类型,我们显示了相应的转换处理结果。
工作流程详解
数据转换的完整流程
- 转换类型选择: 用户在 ArkTS UI 中选择要执行的转换类型
- 数据输入: 用户输入要转换的数据
- 处理执行: 调用 DataConverter 的相应方法
- 结果展示: 将转换结果显示在 UI 中
跨平台一致性
通过 KMP 技术,我们确保了在所有平台上的行为一致性。无论是在 Kotlin/JVM、Kotlin/JS 还是通过 ArkTS 调用,数据转换的逻辑和结果都是完全相同的。
实际应用场景
API 数据处理
在处理 API 返回的数据时,需要进行数据转换。这个工具库提供了完整的 API 数据转换功能。
用户输入处理
在处理用户输入时,需要进行数据转换和验证。这个工具库提供了用户输入转换能力。
数据存储
在存储数据时,需要进行数据转换以适应存储格式。这个工具库提供了数据存储转换功能。
数据展示
在展示数据时,需要进行数据转换以适应展示格式。这个工具库提供了数据展示转换能力。
性能优化
缓存转换结果
在频繁进行相同转换时,可以缓存转换结果以避免重复转换。
批量转换
在转换多个数据时,应该使用批量转换以提高效率。
安全性考虑
类型验证
在进行数据转换时,应该进行类型验证以确保转换的安全性。
错误处理
在转换失败时,应该进行适当的错误处理以提供有用的错误信息。
总结
这个 KMP OpenHarmony 数据转换库示例展示了如何使用现代的跨平台技术来处理常见的数据转换任务。通过 Kotlin Multiplatform 技术,我们可以在一个地方编写业务逻辑,然后在多个平台上使用。
数据转换是应用开发中的基础功能。通过使用这样的工具库,开发者可以快速、可靠地实现各种数据转换操作,从而提高应用的数据处理能力。
在实际应用中,建议根据具体的需求进行定制和扩展,例如添加更多的转换方法、实现更复杂的转换逻辑等高级特性。同时,定期进行测试和优化,确保应用的转换系统保持高效运行。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)