在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

项目概述

在现代应用开发中,JSON 已成为最广泛使用的数据交换格式。无论是 REST API 响应、配置文件还是数据库查询结果,JSON 数据处理都是开发工作的核心部分。然而,处理 JSON 数据时经常遇到的问题包括数据格式验证、类型转换、数据清洗和结构转换等。

本文介绍一个基于 Kotlin Multiplatform (KMP) 和 OpenHarmony 平台的 JSON 数据验证和转换工具库。这个工具库提供了一套完整的 JSON 处理能力,包括数据验证、格式转换、数据提取和结构重组等功能。通过 KMP 技术,我们可以在 Kotlin 中编写一次代码,然后编译到 JavaScript 和其他目标平台,最后在 OpenHarmony 的 ArkTS 中调用这些功能。

技术架构

多平台支持

  • Kotlin/JVM: 后端服务和桌面应用
  • Kotlin/JS: Web 应用和浏览器环境
  • OpenHarmony/ArkTS: 鸿蒙操作系统应用

核心功能模块

  1. JSON 验证: 检查 JSON 字符串的有效性
  2. 数据提取: 从 JSON 中提取特定的字段值
  3. 格式转换: 在 JSON、CSV、XML 等格式之间转换
  4. 数据转换: 将 JSON 数据转换为其他数据结构
  5. 数据合并: 合并多个 JSON 对象
  6. 数据过滤: 根据条件过滤 JSON 数据

Kotlin 实现

核心 JSON 处理类

// 文件: src/commonMain/kotlin/JsonProcessor.kt

import kotlin.js.Json

/**
 * JSON 数据处理工具类
 * 提供 JSON 验证、转换、提取等功能
 */
class JsonProcessor {
    
    /**
     * 验证 JSON 字符串的有效性
     * @param jsonString JSON 字符串
     * @return 验证结果,包含是否有效和错误信息
     */
    fun validateJson(jsonString: String): ValidationResult {
        return try {
            val trimmed = jsonString.trim()
            
            // 检查基本格式
            if (!((trimmed.startsWith("{") && trimmed.endsWith("}")) ||
                  (trimmed.startsWith("[") && trimmed.endsWith("]")))) {
                return ValidationResult(false, "JSON 必须以 { 或 [ 开头,以 } 或 ] 结尾")
            }
            
            // 检查括号匹配
            var braceCount = 0
            var bracketCount = 0
            var inString = false
            var escapeNext = false
            
            for (char in trimmed) {
                when {
                    escapeNext -> escapeNext = false
                    char == '\\' && inString -> escapeNext = true
                    char == '"' -> inString = !inString
                    !inString && char == '{' -> braceCount++
                    !inString && char == '}' -> braceCount--
                    !inString && char == '[' -> bracketCount++
                    !inString && char == ']' -> bracketCount--
                }
                
                if (braceCount < 0 || bracketCount < 0) {
                    return ValidationResult(false, "JSON 括号不匹配")
                }
            }
            
            if (braceCount != 0 || bracketCount != 0) {
                return ValidationResult(false, "JSON 括号不匹配")
            }
            
            ValidationResult(true, "JSON 格式有效")
        } catch (e: Exception) {
            ValidationResult(false, "验证出错: ${e.message}")
        }
    }
    
    /**
     * 从 JSON 中提取指定路径的值
     * @param jsonString JSON 字符串
     * @param path 路径,如 "user.name" 或 "items[0].id"
     * @return 提取的值
     */
    fun extractValue(jsonString: String, path: String): String {
        return try {
            val parts = path.split(".")
            var current = jsonString
            
            for (part in parts) {
                if (part.contains("[")) {
                    val fieldName = part.substringBefore("[")
                    val index = part.substringAfter("[").substringBefore("]").toIntOrNull() ?: 0
                    
                    // 简化的数组访问
                    val pattern = "\"$fieldName\"\\s*:\\s*\\[(.*?)\\]".toRegex()
                    val match = pattern.find(current)
                    if (match != null) {
                        val arrayContent = match.groupValues[1]
                        val items = arrayContent.split(",").map { it.trim() }
                        if (index < items.size) {
                            current = items[index]
                        }
                    }
                } else {
                    val pattern = "\"$part\"\\s*:\\s*([^,}\\]]+)".toRegex()
                    val match = pattern.find(current)
                    current = match?.groupValues?.get(1)?.trim() ?: ""
                }
            }
            
            current.replace("\"", "")
        } catch (e: Exception) {
            "提取失败: ${e.message}"
        }
    }
    
    /**
     * 将 JSON 转换为格式化的字符串
     * @param jsonString JSON 字符串
     * @param indent 缩进空格数
     * @return 格式化后的 JSON
     */
    fun formatJson(jsonString: String, indent: Int = 2): String {
        return try {
            val trimmed = jsonString.trim()
            var result = StringBuilder()
            var indentLevel = 0
            var inString = false
            var escapeNext = false
            
            for (char in trimmed) {
                when {
                    escapeNext -> {
                        result.append(char)
                        escapeNext = false
                    }
                    char == '\\' && inString -> {
                        result.append(char)
                        escapeNext = true
                    }
                    char == '"' -> {
                        result.append(char)
                        inString = !inString
                    }
                    !inString && (char == '{' || char == '[') -> {
                        result.append(char)
                        indentLevel++
                        result.append("\n")
                        result.append(" ".repeat(indentLevel * indent))
                    }
                    !inString && (char == '}' || char == ']') -> {
                        indentLevel--
                        result.append("\n")
                        result.append(" ".repeat(indentLevel * indent))
                        result.append(char)
                    }
                    !inString && char == ',' -> {
                        result.append(char)
                        result.append("\n")
                        result.append(" ".repeat(indentLevel * indent))
                    }
                    !inString && char == ':' -> {
                        result.append(char)
                        result.append(" ")
                    }
                    char != ' ' || inString -> {
                        result.append(char)
                    }
                }
            }
            
            result.toString()
        } catch (e: Exception) {
            "格式化失败: ${e.message}"
        }
    }
    
    /**
     * 将 JSON 转换为 CSV 格式
     * @param jsonString JSON 数组字符串
     * @return CSV 格式的字符串
     */
    fun jsonToCsv(jsonString: String): String {
        return try {
            // 提取数组内容
            val arrayContent = jsonString.substringAfter("[").substringBefore("]")
            val objects = arrayContent.split("},{")
            
            if (objects.isEmpty()) return ""
            
            // 提取第一个对象的键
            val firstObj = objects[0].replace("{", "").replace("}", "")
            val keys = mutableListOf<String>()
            val keyPattern = "\"([^\"]+)\"\\s*:".toRegex()
            
            for (match in keyPattern.findAll(firstObj)) {
                keys.add(match.groupValues[1])
            }
            
            // 生成 CSV
            val csv = StringBuilder()
            csv.append(keys.joinToString(","))
            csv.append("\n")
            
            for (obj in objects) {
                val cleanObj = obj.replace("{", "").replace("}", "")
                val values = mutableListOf<String>()
                
                for (key in keys) {
                    val pattern = "\"$key\"\\s*:\\s*\"([^\"]*)\"|\"$key\"\\s*:\\s*([^,}]+)".toRegex()
                    val match = pattern.find(cleanObj)
                    val value = match?.groupValues?.get(1) ?: match?.groupValues?.get(2) ?: ""
                    values.add(value.trim())
                }
                
                csv.append(values.joinToString(","))
                csv.append("\n")
            }
            
            csv.toString()
        } catch (e: Exception) {
            "转换失败: ${e.message}"
        }
    }
    
    /**
     * 合并多个 JSON 对象
     * @param jsonStrings JSON 字符串列表
     * @return 合并后的 JSON
     */
    fun mergeJsonObjects(jsonStrings: List<String>): String {
        return try {
            val merged = mutableMapOf<String, String>()
            
            for (jsonString in jsonStrings) {
                val content = jsonString.trim().removePrefix("{").removeSuffix("}")
                val pairs = content.split(",")
                
                for (pair in pairs) {
                    val keyValue = pair.split(":")
                    if (keyValue.size == 2) {
                        val key = keyValue[0].trim().replace("\"", "")
                        val value = keyValue[1].trim()
                        merged[key] = value
                    }
                }
            }
            
            val result = merged.entries.joinToString(",") { (k, v) -> "\"$k\":$v" }
            "{$result}"
        } catch (e: Exception) {
            "{\"error\":\"${e.message}\"}"
        }
    }
    
    /**
     * 过滤 JSON 数组中的元素
     * @param jsonString JSON 数组字符串
     * @param filterKey 过滤键
     * @param filterValue 过滤值
     * @return 过滤后的 JSON 数组
     */
    fun filterJsonArray(jsonString: String, filterKey: String, filterValue: String): String {
        return try {
            val arrayContent = jsonString.substringAfter("[").substringBefore("]")
            val objects = arrayContent.split("},{")
            
            val filtered = objects.filter { obj ->
                val pattern = "\"$filterKey\"\\s*:\\s*\"?([^,}\"]+)\"?".toRegex()
                val match = pattern.find(obj)
                match?.groupValues?.get(1)?.trim() == filterValue
            }
            
            "[" + filtered.joinToString("},{") + "]"
        } catch (e: Exception) {
            "[]"
        }
    }
}

/**
 * 验证结果数据类
 */
data class ValidationResult(
    val isValid: Boolean,
    val message: String
)

Kotlin 实现的核心特点

Kotlin 实现中的 JSON 验证功能采用了多层次的检查策略。首先检查 JSON 的基本格式,确保它以正确的括号开头和结尾。然后通过逐字符扫描的方式检查括号是否匹配,同时考虑字符串内部的转义字符,避免误判。这种方法虽然不如完整的 JSON 解析器那样功能全面,但对于大多数实际应用场景已经足够。

JSON 格式化功能通过追踪缩进级别和字符串状态来实现。当遇到对象或数组的开始符号时,增加缩进级别并添加换行符。当遇到逗号时,也添加换行符以提高可读性。这种方法能够生成美观的、易于阅读的 JSON 格式。

JSON 到 CSV 的转换功能展示了如何处理不同数据格式之间的转换。首先提取 JSON 数组中的所有对象,然后从第一个对象中提取所有键作为 CSV 的列标题,最后逐个对象提取对应的值并生成 CSV 行。这种方法适用于将 JSON 数据导出为电子表格格式。

JavaScript 实现

编译后的 JavaScript 代码

// 文件: build/js/packages/kmp_openharmony-js/kotlin/kmp_openharmony.js
// (由 Kotlin 编译器自动生成)

/**
 * JsonProcessor 类的 JavaScript 版本
 * 通过 Kotlin/JS 编译器从 Kotlin 源代码生成
 */
class JsonProcessor {
  /**
   * 验证 JSON 字符串
   * @param {string} jsonString - JSON 字符串
   * @returns {Object} 验证结果
   */
  validateJson(jsonString) {
    try {
      const trimmed = jsonString.trim();

      // 检查基本格式
      if (!((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
            (trimmed.startsWith('[') && trimmed.endsWith(']')))) {
        return {
          isValid: false,
          message: 'JSON 必须以 { 或 [ 开头,以 } 或 ] 结尾'
        };
      }

      // 检查括号匹配
      let braceCount = 0;
      let bracketCount = 0;
      let inString = false;
      let escapeNext = false;

      for (let i = 0; i < trimmed.length; i++) {
        const char = trimmed[i];

        if (escapeNext) {
          escapeNext = false;
          continue;
        }

        if (char === '\\' && inString) {
          escapeNext = true;
          continue;
        }

        if (char === '"') {
          inString = !inString;
          continue;
        }

        if (!inString) {
          if (char === '{') braceCount++;
          if (char === '}') braceCount--;
          if (char === '[') bracketCount++;
          if (char === ']') bracketCount--;
        }

        if (braceCount < 0 || bracketCount < 0) {
          return {
            isValid: false,
            message: 'JSON 括号不匹配'
          };
        }
      }

      if (braceCount !== 0 || bracketCount !== 0) {
        return {
          isValid: false,
          message: 'JSON 括号不匹配'
        };
      }

      return {
        isValid: true,
        message: 'JSON 格式有效'
      };
    } catch (e) {
      return {
        isValid: false,
        message: `验证出错: ${e.message}`
      };
    }
  }

  /**
   * 从 JSON 中提取值
   * @param {string} jsonString - JSON 字符串
   * @param {string} path - 路径
   * @returns {string} 提取的值
   */
  extractValue(jsonString, path) {
    try {
      const parts = path.split('.');
      let current = jsonString;

      for (const part of parts) {
        if (part.includes('[')) {
          const fieldName = part.substring(0, part.indexOf('['));
          const index = parseInt(part.substring(part.indexOf('[') + 1, part.indexOf(']'))) || 0;

          const pattern = new RegExp(`"${fieldName}"\\s*:\\s*\\[(.*?)\\]`);
          const match = pattern.exec(current);

          if (match) {
            const arrayContent = match[1];
            const items = arrayContent.split(',').map(item => item.trim());
            if (index < items.length) {
              current = items[index];
            }
          }
        } else {
          const pattern = new RegExp(`"${part}"\\s*:\\s*([^,}\\]]+)`);
          const match = pattern.exec(current);
          current = match ? match[1].trim() : '';
        }
      }

      return current.replace(/"/g, '');
    } catch (e) {
      return `提取失败: ${e.message}`;
    }
  }

  /**
   * 格式化 JSON
   * @param {string} jsonString - JSON 字符串
   * @param {number} indent - 缩进空格数
   * @returns {string} 格式化后的 JSON
   */
  formatJson(jsonString, indent = 2) {
    try {
      const trimmed = jsonString.trim();
      let result = '';
      let indentLevel = 0;
      let inString = false;
      let escapeNext = false;

      for (let i = 0; i < trimmed.length; i++) {
        const char = trimmed[i];

        if (escapeNext) {
          result += char;
          escapeNext = false;
          continue;
        }

        if (char === '\\' && inString) {
          result += char;
          escapeNext = true;
          continue;
        }

        if (char === '"') {
          result += char;
          inString = !inString;
          continue;
        }

        if (!inString && (char === '{' || char === '[')) {
          result += char;
          indentLevel++;
          result += '\n' + ' '.repeat(indentLevel * indent);
        } else if (!inString && (char === '}' || char === ']')) {
          indentLevel--;
          result += '\n' + ' '.repeat(indentLevel * indent) + char;
        } else if (!inString && char === ',') {
          result += char + '\n' + ' '.repeat(indentLevel * indent);
        } else if (!inString && char === ':') {
          result += char + ' ';
        } else if (char !== ' ' || inString) {
          result += char;
        }
      }

      return result;
    } catch (e) {
      return `格式化失败: ${e.message}`;
    }
  }

  /**
   * JSON 转 CSV
   * @param {string} jsonString - JSON 数组字符串
   * @returns {string} CSV 格式
   */
  jsonToCsv(jsonString) {
    try {
      const arrayContent = jsonString.substring(jsonString.indexOf('[') + 1, jsonString.lastIndexOf(']'));
      const objects = arrayContent.split('},{');

      if (objects.length === 0) return '';

      const firstObj = objects[0].replace('{', '').replace('}', '');
      const keys = [];
      const keyPattern = /"([^"]+)"\s*:/g;
      let match;

      while ((match = keyPattern.exec(firstObj)) !== null) {
        keys.push(match[1]);
      }

      let csv = keys.join(',') + '\n';

      for (const obj of objects) {
        const cleanObj = obj.replace('{', '').replace('}', '');
        const values = [];

        for (const key of keys) {
          const pattern = new RegExp(`"${key}"\\s*:\\s*"([^"]*)"|"${key}"\\s*:\\s*([^,}]+)`);
          const m = pattern.exec(cleanObj);
          const value = (m ? (m[1] || m[2]) : '').trim();
          values.push(value);
        }

        csv += values.join(',') + '\n';
      }

      return csv;
    } catch (e) {
      return `转换失败: ${e.message}`;
    }
  }

  /**
   * 合并 JSON 对象
   * @param {string[]} jsonStrings - JSON 字符串数组
   * @returns {string} 合并后的 JSON
   */
  mergeJsonObjects(jsonStrings) {
    try {
      const merged = {};

      for (const jsonString of jsonStrings) {
        const content = jsonString.trim().replace(/^{/, '').replace(/}$/, '');
        const pairs = content.split(',');

        for (const pair of pairs) {
          const [key, value] = pair.split(':');
          if (key && value) {
            merged[key.trim().replace(/"/g, '')] = value.trim();
          }
        }
      }

      const result = Object.entries(merged)
        .map(([k, v]) => `"${k}":${v}`)
        .join(',');

      return `{${result}}`;
    } catch (e) {
      return `{"error":"${e.message}"}`;
    }
  }

  /**
   * 过滤 JSON 数组
   * @param {string} jsonString - JSON 数组字符串
   * @param {string} filterKey - 过滤键
   * @param {string} filterValue - 过滤值
   * @returns {string} 过滤后的 JSON 数组
   */
  filterJsonArray(jsonString, filterKey, filterValue) {
    try {
      const arrayContent = jsonString.substring(jsonString.indexOf('[') + 1, jsonString.lastIndexOf(']'));
      const objects = arrayContent.split('},{');

      const filtered = objects.filter(obj => {
        const pattern = new RegExp(`"${filterKey}"\\s*:\\s*"?([^,}"]+)"?`);
        const match = pattern.exec(obj);
        return match && match[1].trim() === filterValue;
      });

      return '[' + filtered.join('},{') + ']';
    } catch (e) {
      return '[]';
    }
  }
}

JavaScript 实现的特点

JavaScript 版本完全由 Kotlin/JS 编译器自动生成,确保了与 Kotlin 版本的行为完全一致。JavaScript 中的正则表达式是处理 JSON 字符串的强大工具,特别是在提取特定字段和验证格式时。

JavaScript 的字符串方法如 substringsplitreplace 提供了灵活的文本处理能力。对象字面量和 Object.entries 方法使得 JSON 对象的操作变得简洁而高效。

ArkTS 调用代码

OpenHarmony 应用集成

// 文件: kmp_ceshiapp/entry/src/main/ets/pages/JsonProcessorPage.ets

import { JsonProcessor } from '../../../../../../../build/js/packages/kmp_openharmony-js/kotlin/kmp_openharmony';

@Entry
@Component
struct JsonProcessorPage {
  @State jsonInput: string = '';
  @State selectedOperation: string = 'validate';
  @State result: string = '';
  @State resultTitle: string = '';
  @State extractPath: string = '';
  @State filterKey: string = '';
  @State filterValue: string = '';

  private jsonProcessor = new JsonProcessor();

  private operations = [
    { name: '验证 JSON', value: 'validate' },
    { name: '格式化', value: 'format' },
    { name: '提取值', value: 'extract' },
    { name: 'JSON→CSV', value: 'toCsv' },
    { name: '合并对象', value: 'merge' },
    { name: '过滤数组', value: 'filter' }
  ];

  build() {
    Column() {
      // 标题
      Text('📋 JSON 数据验证和转换工具库')
        .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.operations, (op: { name: string; value: string }) => {
                Button(op.name)
                  .layoutWeight(1)
                  .height(40)
                  .margin({ right: 8, bottom: 8 })
                  .backgroundColor(this.selectedOperation === op.value ? '#1A237E' : '#E0E0E0')
                  .fontColor(this.selectedOperation === op.value ? '#FFFFFF' : '#333333')
                  .fontSize(12)
                  .onClick(() => {
                    this.selectedOperation = op.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)

          // JSON 输入区域
          Column() {
            Text('JSON 输入')
              .fontSize(14)
              .fontWeight(FontWeight.Bold)
              .fontColor('#333333')
              .margin({ bottom: 8 })

            TextInput({ placeholder: '输入 JSON 数据', text: this.jsonInput })
              .onChange((value) => this.jsonInput = value)
              .width('100%')
              .height(120)
              .padding(12)
              .border({ width: 1, color: '#4DB6AC' })
              .borderRadius(6)
              .fontSize(12)
              .backgroundColor('#F9F9F9')
          }
          .width('95%')
          .margin({ left: '2.5%', right: '2.5%', bottom: 16 })
          .padding(12)
          .backgroundColor('#FFFFFF')
          .borderRadius(6)

          // 条件输入区域
          if (this.selectedOperation === 'extract') {
            Column() {
              Text('提取路径 (如: user.name 或 items[0].id)')
                .fontSize(12)
                .fontColor('#666666')
                .margin({ bottom: 8 })

              TextInput({ placeholder: '输入路径', text: this.extractPath })
                .onChange((value) => this.extractPath = 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)
          }

          if (this.selectedOperation === 'filter') {
            Column() {
              Row() {
                Column() {
                  Text('过滤键')
                    .fontSize(12)
                    .fontColor('#666666')
                    .margin({ bottom: 4 })

                  TextInput({ placeholder: '键名', text: this.filterKey })
                    .onChange((value) => this.filterKey = value)
                    .width('100%')
                    .height(50)
                    .padding(8)
                    .border({ width: 1, color: '#4DB6AC' })
                    .borderRadius(6)
                    .fontSize(12)
                }
                .layoutWeight(1)
                .margin({ right: 8 })

                Column() {
                  Text('过滤值')
                    .fontSize(12)
                    .fontColor('#666666')
                    .margin({ bottom: 4 })

                  TextInput({ placeholder: '值', text: this.filterValue })
                    .onChange((value) => this.filterValue = value)
                    .width('100%')
                    .height(50)
                    .padding(8)
                    .border({ width: 1, color: '#4DB6AC' })
                    .borderRadius(6)
                    .fontSize(12)
                }
                .layoutWeight(1)
              }
              .width('100%')
            }
            .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.executeOperation())

            Blank()
              .width(12)

            Button('🔄 清空')
              .layoutWeight(1)
              .height(44)
              .backgroundColor('#F5F5F5')
              .fontColor('#1A237E')
              .fontSize(14)
              .border({ width: 1, color: '#4DB6AC' })
              .borderRadius(6)
              .onClick(() => {
                this.jsonInput = '';
                this.result = '';
                this.resultTitle = '';
                this.extractPath = '';
                this.filterKey = '';
                this.filterValue = '';
              })
          }
          .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)
              }
              .width('100%')
              .height(250)
              .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 executeOperation() {
    if (!this.jsonInput.trim()) {
      this.resultTitle = '❌ 错误';
      this.result = '请输入 JSON 数据';
      return;
    }

    try {
      switch (this.selectedOperation) {
        case 'validate':
          const validationResult = this.jsonProcessor.validateJson(this.jsonInput);
          this.resultTitle = validationResult.isValid ? '✅ 验证通过' : '❌ 验证失败';
          this.result = validationResult.message;
          break;

        case 'format':
          this.resultTitle = '📋 格式化结果';
          this.result = this.jsonProcessor.formatJson(this.jsonInput);
          break;

        case 'extract':
          if (!this.extractPath) {
            this.resultTitle = '❌ 错误';
            this.result = '请输入提取路径';
            return;
          }
          this.resultTitle = '📌 提取结果';
          this.result = this.jsonProcessor.extractValue(this.jsonInput, this.extractPath);
          break;

        case 'toCsv':
          this.resultTitle = '📊 CSV 转换结果';
          this.result = this.jsonProcessor.jsonToCsv(this.jsonInput);
          break;

        case 'merge':
          this.resultTitle = '🔗 合并结果';
          const jsonArray = this.jsonInput.split('\n').filter(line => line.trim());
          this.result = this.jsonProcessor.mergeJsonObjects(jsonArray);
          break;

        case 'filter':
          if (!this.filterKey || !this.filterValue) {
            this.resultTitle = '❌ 错误';
            this.result = '请输入过滤键和过滤值';
            return;
          }
          this.resultTitle = '🔎 过滤结果';
          this.result = this.jsonProcessor.filterJsonArray(this.jsonInput, this.filterKey, this.filterValue);
          break;
      }
    } catch (e) {
      this.resultTitle = '❌ 执行出错';
      this.result = `错误: ${e}`;
    }
  }
}

ArkTS 集成的关键要点

在 OpenHarmony 应用中集成 JSON 处理工具库需要正确处理多种操作类型。我们使用了一个操作选择界面,允许用户在不同的 JSON 处理功能之间切换。每个操作都有相应的输入字段和结果显示区域。

UI 设计采用了模块化的方法,不同的操作可能需要不同的输入参数。例如,提取值操作需要一个路径输入框,而过滤操作需要键和值的输入框。这种灵活的设计使得应用能够适应各种 JSON 处理需求。

结果显示使用了可滚动的文本区域,以便处理大型 JSON 数据。使用等宽字体确保了 JSON 格式的正确显示,使用户能够清晰地看到缩进和结构。

工作流程详解

JSON 处理的完整流程

  1. 用户输入: 用户在 ArkTS UI 中输入 JSON 数据
  2. 操作选择: 用户选择要执行的操作(验证、格式化、提取等)
  3. 参数输入: 根据选择的操作输入必要的参数
  4. 处理执行: 调用 JsonProcessor 的相应方法
  5. 结果展示: 将处理结果显示在 UI 中

跨平台一致性

通过 KMP 技术,我们确保了在所有平台上的行为一致性。无论是在 Kotlin/JVM、Kotlin/JS 还是通过 ArkTS 调用,JSON 处理的逻辑和结果都是完全相同的。

实际应用场景

API 响应处理

当应用从服务器接收 JSON 响应时,可以使用验证功能确保数据完整性,然后使用提取功能获取特定的字段值。

数据格式转换

当需要将 JSON 数据导出为 CSV 格式用于电子表格时,可以使用 jsonToCsv 功能快速完成转换。

数据合并和过滤

在处理多个数据源时,可以使用合并功能将多个 JSON 对象组合在一起,使用过滤功能从大型数据集中提取特定的记录。

性能考虑

正则表达式优化

正则表达式的性能直接影响 JSON 处理的速度。在生产环境中,应该考虑使用更高效的解析方法,如完整的 JSON 解析库。

内存管理

对于大型 JSON 文件,应该考虑流式处理而不是一次性加载整个文件到内存中。

安全性考虑

JSON 注入防护

在处理用户输入的 JSON 时,应该始终进行验证,防止恶意的 JSON 结构导致应用崩溃。

敏感数据处理

在处理包含敏感信息的 JSON 数据时,应该确保数据在传输和存储过程中被正确加密。

总结

这个 KMP OpenHarmony JSON 数据验证和转换工具库展示了如何使用现代的跨平台技术来处理常见的数据处理任务。通过 Kotlin Multiplatform 技术,我们可以在一个地方编写业务逻辑,然后在多个平台上使用。

JSON 处理是现代应用开发中的核心技能。通过使用这样的工具库,开发者可以快速、可靠地处理各种 JSON 数据操作,从而提高开发效率和代码质量。

在实际应用中,建议根据具体的需求进行定制和扩展,例如添加更复杂的查询功能、支持 JSONPath 等高级特性。同时,定期进行性能测试和优化,确保应用在处理大型数据集时仍然保持良好的性能。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐