在这里插入图片描述

目录

  1. 概述
  2. 工具功能
  3. 核心实现
  4. Kotlin 源代码
  5. JavaScript 编译代码
  6. ArkTS 调用代码
  7. 实战案例
  8. 最佳实践

概述

本文档介绍如何在 Kotlin Multiplatform (KMP) 鸿蒙跨端开发中实现一个完整的 JSON 格式化和验证工具系统。JSON(JavaScript Object Notation)是现代应用开发中最广泛使用的数据交换格式,涉及数据解析、格式验证、结构转换等多个方面。无论是进行 API 开发、数据存储还是配置管理,一个功能强大的 JSON 工具都能提供便利的支持。

这个案例展示了如何使用 Kotlin 的字符串处理、递归算法和正则表达式来创建一个功能丰富的 JSON 分析工具。JSON 格式化和验证工具需要能够验证 JSON 的合法性、格式化 JSON 使其更易读、压缩 JSON 减小体积、提取 JSON 中的特定字段、合并多个 JSON 对象等。通过 KMP,这个工具可以无缝编译到 JavaScript,在 OpenHarmony 应用中运行,并支持用户输入进行实时 JSON 处理。

在实际应用中,JSON 工具广泛应用于以下场景:Web API 的请求和响应处理、移动应用的数据存储和传输、配置文件的管理和验证、日志数据的解析和分析、前后端数据交互等。通过支持多种 JSON 操作如验证、格式化、压缩、查询和转换,我们可以满足不同场景的需求。同时,通过 KMP 框架的跨端能力,我们可以在不同平台上使用相同的 JSON 处理逻辑,确保数据处理的一致性和可靠性。

工具的特点

  • 格式验证:验证 JSON 字符串的合法性和结构完整性
  • 格式化处理:支持美化、压缩、缩进等多种格式化方式
  • 路径查询:支持 JSONPath 查询特定的数据字段
  • 数据转换:支持 JSON 与其他格式的相互转换
  • 错误定位:精确定位 JSON 错误的位置和原因
  • 跨端兼容:一份 Kotlin 代码可同时服务多个平台

工具功能

1. JSON 验证

JSON 验证是处理 JSON 数据的第一步,需要检查 JSON 字符串是否符合 JSON 规范。合法的 JSON 必须包含正确的括号匹配、引号配对、逗号分隔等。验证过程中需要处理各种边界情况,如空字符串、嵌套对象、数组等。通过验证,我们可以确保后续的 JSON 处理操作不会因为格式错误而失败。

  • 语法检查:检查 JSON 的基本语法是否正确
  • 结构验证:验证 JSON 的嵌套结构是否完整
  • 类型检查:验证 JSON 中各个值的类型是否正确
  • 错误报告:提供详细的错误信息和错误位置

2. JSON 格式化

JSON 格式化是将紧凑的 JSON 字符串转换为易于阅读的格式。通过添加适当的缩进和换行,可以使 JSON 的结构更加清晰。格式化后的 JSON 便于开发者进行调试和理解。此外,格式化还可以帮助识别 JSON 中的错误,因为格式化过程会检查 JSON 的合法性。

  • 美化处理:添加缩进和换行使 JSON 更易读
  • 压缩处理:移除不必要的空格和换行减小体积
  • 自定义缩进:支持自定义缩进字符和缩进大小
  • 保留原始数据:确保格式化前后的数据内容不变

3. JSON 查询

JSON 查询允许用户快速定位和提取 JSON 中的特定数据。通过使用路径表达式,可以访问嵌套的对象和数组元素。这对于处理复杂的 JSON 结构特别有用,可以避免手动遍历整个 JSON 树。

  • 路径查询:使用点符号或括号符号访问嵌套数据
  • 数组索引:支持通过索引访问数组元素
  • 通配符查询:支持使用通配符查询多个字段
  • 条件查询:支持基于条件的查询操作

4. JSON 转换

JSON 转换涉及将 JSON 数据转换为其他格式,或者从其他格式转换为 JSON。常见的转换包括 JSON 到 CSV、JSON 到 XML、JSON 到 YAML 等。这些转换对于数据交互和集成特别有用。

  • JSON 到对象:将 JSON 字符串解析为对象
  • 对象到 JSON:将对象序列化为 JSON 字符串
  • 格式转换:支持与其他数据格式的转换
  • 数据映射:支持字段映射和数据转换

5. JSON 合并和比较

JSON 合并允许将多个 JSON 对象合并为一个。这对于合并配置文件、合并 API 响应等场景特别有用。JSON 比较可以识别两个 JSON 对象之间的差异,用于版本控制和数据同步。

  • 深度合并:递归合并嵌套的 JSON 对象
  • 数组合并:支持多种数组合并策略
  • 差异比较:识别两个 JSON 对象的差异
  • 补丁生成:生成 JSON 补丁用于更新

核心实现

1. JSON 验证

fun isValidJson(json: String): Boolean {
    val trimmed = json.trim()
    if (trimmed.isEmpty()) return false
    
    var depth = 0
    var inString = false
    var escapeNext = false
    
    for (char in trimmed) {
        when {
            escapeNext -> escapeNext = false
            char == '\\' && inString -> escapeNext = true
            char == '"' -> inString = !inString
            !inString -> {
                when (char) {
                    '{', '[' -> depth++
                    '}', ']' -> {
                        depth--
                        if (depth < 0) return false
                    }
                }
            }
        }
    }
    
    return depth == 0 && !inString && (trimmed[0] == '{' || trimmed[0] == '[')
}

代码说明: JSON 验证通过跟踪括号的深度和字符串状态来实现。我们遍历 JSON 字符串的每个字符,跟踪是否在字符串内部(用于忽略字符串中的特殊字符)、是否需要转义下一个字符。对于非字符串部分,我们计算括号的深度,确保每个开括号都有对应的闭括号。最后,验证深度为 0(所有括号都匹配)且字符串没有未闭合的引号。

2. JSON 格式化

fun formatJson(json: String, indent: Int = 2): String {
    if (!isValidJson(json)) return "Invalid JSON"
    
    val trimmed = json.trim()
    val result = StringBuilder()
    var indentLevel = 0
    var inString = false
    var escapeNext = false
    val indentStr = " ".repeat(indent)
    
    for (i in trimmed.indices) {
        val char = trimmed[i]
        
        when {
            escapeNext -> {
                result.append(char)
                escapeNext = false
            }
            char == '\\' && inString -> {
                result.append(char)
                escapeNext = true
            }
            char == '"' -> {
                result.append(char)
                inString = !inString
            }
            !inString -> {
                when (char) {
                    '{', '[' -> {
                        result.append(char)
                        indentLevel++
                        result.append('\n')
                        result.append(indentStr.repeat(indentLevel))
                    }
                    '}', ']' -> {
                        indentLevel--
                        result.append('\n')
                        result.append(indentStr.repeat(indentLevel))
                        result.append(char)
                    }
                    ',' -> {
                        result.append(char)
                        result.append('\n')
                        result.append(indentStr.repeat(indentLevel))
                    }
                    ':' -> {
                        result.append(char)
                        result.append(' ')
                    }
                    ' ' -> {} // 忽略空格
                    else -> result.append(char)
                }
            }
            else -> result.append(char)
        }
    }
    
    return result.toString()
}

代码说明: JSON 格式化通过在适当的位置添加换行和缩进来实现。我们遍历 JSON 字符串,跟踪当前的缩进级别。当遇到开括号时,增加缩进级别并添加换行。当遇到闭括号时,减少缩进级别并添加换行。对于逗号,添加换行并恢复到当前缩进级别。对于冒号,添加空格以提高可读性。字符串内的所有字符都保持原样,不进行任何修改。

3. JSON 压缩

fun minifyJson(json: String): String {
    if (!isValidJson(json)) return "Invalid JSON"
    
    val result = StringBuilder()
    var inString = false
    var escapeNext = false
    
    for (char in json) {
        when {
            escapeNext -> {
                result.append(char)
                escapeNext = false
            }
            char == '\\' && inString -> {
                result.append(char)
                escapeNext = true
            }
            char == '"' -> {
                result.append(char)
                inString = !inString
            }
            !inString && char.isWhitespace() -> {} // 忽略空格
            else -> result.append(char)
        }
    }
    
    return result.toString()
}

代码说明: JSON 压缩是格式化的反向过程,移除所有不必要的空格和换行。我们遍历 JSON 字符串,跳过字符串外的所有空白字符。这样可以显著减小 JSON 的体积,特别是对于大型 JSON 数据。

4. JSON 路径查询

fun getJsonValue(json: String, path: String): String {
    if (!isValidJson(json)) return "Invalid JSON"
    
    val parts = path.split(".")
    var current = json.trim()
    
    for (part in parts) {
        if (part.isEmpty()) continue
        
        current = when {
            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 elements = arrayContent.split(",").map { it.trim() }
                    if (index < elements.size) elements[index] else "null"
                } else "null"
            }
            else -> {
                val pattern = "\"$part\"\\s*:\\s*([^,}\\]]+)".toRegex()
                val match = pattern.find(current)
                match?.groupValues?.get(1)?.trim() ?: "null"
            }
        }
    }
    
    return current
}

代码说明: JSON 路径查询使用正则表达式来定位和提取 JSON 中的特定值。我们将路径分解为多个部分,然后逐个处理。对于对象字段,使用正则表达式找到对应的值。对于数组元素,先找到数组,然后按索引提取元素。这个实现支持基本的路径查询,可以扩展以支持更复杂的 JSONPath 表达式。

5. JSON 合并

fun mergeJson(json1: String, json2: String): String {
    if (!isValidJson(json1) || !isValidJson(json2)) return "Invalid JSON"
    
    // 简化实现:将两个 JSON 对象的内容合并
    val trimmed1 = json1.trim().removeSurrounding("{", "}")
    val trimmed2 = json2.trim().removeSurrounding("{", "}")
    
    val merged = if (trimmed1.isEmpty()) {
        trimmed2
    } else if (trimmed2.isEmpty()) {
        trimmed1
    } else {
        "$trimmed1,$trimmed2"
    }
    
    return "{$merged}"
}

代码说明: JSON 合并通过组合两个 JSON 对象的内容来实现。我们移除外层的括号,将两个对象的内容用逗号连接,然后添加外层括号。这个实现适用于简单的对象合并。对于更复杂的场景(如处理重复的键),需要更复杂的实现。


Kotlin 源代码

// JsonFormatterValidator.kt
class JsonFormatterValidator {
    
    fun isValidJson(json: String): Boolean {
        val trimmed = json.trim()
        if (trimmed.isEmpty()) return false
        
        var depth = 0
        var inString = false
        var escapeNext = false
        
        for (char in trimmed) {
            when {
                escapeNext -> escapeNext = false
                char == '\\' && inString -> escapeNext = true
                char == '"' -> inString = !inString
                !inString -> {
                    when (char) {
                        '{', '[' -> depth++
                        '}', ']' -> {
                            depth--
                            if (depth < 0) return false
                        }
                    }
                }
            }
        }
        
        return depth == 0 && !inString && (trimmed[0] == '{' || trimmed[0] == '[')
    }
    
    fun formatJson(json: String, indent: Int = 2): String {
        if (!isValidJson(json)) return "Invalid JSON"
        
        val trimmed = json.trim()
        val result = StringBuilder()
        var indentLevel = 0
        var inString = false
        var escapeNext = false
        val indentStr = " ".repeat(indent)
        
        for (i in trimmed.indices) {
            val char = trimmed[i]
            
            when {
                escapeNext -> {
                    result.append(char)
                    escapeNext = false
                }
                char == '\\' && inString -> {
                    result.append(char)
                    escapeNext = true
                }
                char == '"' -> {
                    result.append(char)
                    inString = !inString
                }
                !inString -> {
                    when (char) {
                        '{', '[' -> {
                            result.append(char)
                            indentLevel++
                            result.append('\n')
                            result.append(indentStr.repeat(indentLevel))
                        }
                        '}', ']' -> {
                            indentLevel--
                            result.append('\n')
                            result.append(indentStr.repeat(indentLevel))
                            result.append(char)
                        }
                        ',' -> {
                            result.append(char)
                            result.append('\n')
                            result.append(indentStr.repeat(indentLevel))
                        }
                        ':' -> {
                            result.append(char)
                            result.append(' ')
                        }
                        ' ' -> {}
                        else -> result.append(char)
                    }
                }
                else -> result.append(char)
            }
        }
        
        return result.toString()
    }
    
    fun minifyJson(json: String): String {
        if (!isValidJson(json)) return "Invalid JSON"
        
        val result = StringBuilder()
        var inString = false
        var escapeNext = false
        
        for (char in json) {
            when {
                escapeNext -> {
                    result.append(char)
                    escapeNext = false
                }
                char == '\\' && inString -> {
                    result.append(char)
                    escapeNext = true
                }
                char == '"' -> {
                    result.append(char)
                    inString = !inString
                }
                !inString && char.isWhitespace() -> {}
                else -> result.append(char)
            }
        }
        
        return result.toString()
    }
    
    fun getJsonValue(json: String, path: String): String {
        if (!isValidJson(json)) return "Invalid JSON"
        
        val parts = path.split(".")
        var current = json.trim()
        
        for (part in parts) {
            if (part.isEmpty()) continue
            
            current = when {
                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 elements = arrayContent.split(",").map { it.trim() }
                        if (index < elements.size) elements[index] else "null"
                    } else "null"
                }
                else -> {
                    val pattern = "\"$part\"\\s*:\\s*([^,}\\]]+)".toRegex()
                    val match = pattern.find(current)
                    match?.groupValues?.get(1)?.trim() ?: "null"
                }
            }
        }
        
        return current
    }
    
    fun mergeJson(json1: String, json2: String): String {
        if (!isValidJson(json1) || !isValidJson(json2)) return "Invalid JSON"
        
        val trimmed1 = json1.trim().removeSurrounding("{", "}")
        val trimmed2 = json2.trim().removeSurrounding("{", "}")
        
        val merged = if (trimmed1.isEmpty()) {
            trimmed2
        } else if (trimmed2.isEmpty()) {
            trimmed1
        } else {
            "$trimmed1,$trimmed2"
        }
        
        return "{$merged}"
    }
    
    fun analyzeJson(json: String): Map<String, Any> {
        if (!isValidJson(json)) {
            return mapOf("valid" to false, "error" to "Invalid JSON format")
        }
        
        val trimmed = json.trim()
        var objectCount = 0
        var arrayCount = 0
        var stringCount = 0
        var numberCount = 0
        var inString = false
        var escapeNext = false
        
        for (char in trimmed) {
            when {
                escapeNext -> escapeNext = false
                char == '\\' && inString -> escapeNext = true
                char == '"' -> {
                    inString = !inString
                    if (inString) stringCount++
                }
                !inString -> {
                    when (char) {
                        '{' -> objectCount++
                        '[' -> arrayCount++
                        in '0'..'9', '-' -> numberCount++
                    }
                }
            }
        }
        
        return mapOf(
            "valid" to true,
            "type" to if (trimmed[0] == '{') "Object" else "Array",
            "objects" to objectCount,
            "arrays" to arrayCount,
            "strings" to stringCount,
            "size" to trimmed.length
        )
    }
}

fun main() {
    val tool = JsonFormatterValidator()
    
    val json = """{"name":"John","age":30,"city":"New York"}"""
    
    println("原始 JSON: $json")
    println("验证结果: ${tool.isValidJson(json)}")
    println("格式化后:\n${tool.formatJson(json)}")
    println("压缩后: ${tool.minifyJson(json)}")
    println("查询 name: ${tool.getJsonValue(json, "name")}")
    println("分析结果: ${tool.analyzeJson(json)}")
}

Kotlin 代码说明: 这个实现提供了完整的 JSON 处理功能。JsonFormatterValidator 类包含了验证、格式化、压缩、查询和分析等多个方法。每个方法都有明确的输入验证和错误处理。验证方法通过跟踪括号深度和字符串状态来确保 JSON 的合法性。格式化方法通过添加适当的缩进和换行来提高可读性。查询方法使用正则表达式来定位特定的 JSON 值。


JavaScript 编译代码

// JsonFormatterValidator.js
class JsonFormatterValidator {
    isValidJson(json) {
        const trimmed = json.trim();
        if (trimmed.length === 0) return false;
        
        let depth = 0;
        let inString = false;
        let escapeNext = false;
        
        for (let char of trimmed) {
            if (escapeNext) {
                escapeNext = false;
            } else if (char === '\\' && inString) {
                escapeNext = true;
            } else if (char === '"') {
                inString = !inString;
            } else if (!inString) {
                if (char === '{' || char === '[') {
                    depth++;
                } else if (char === '}' || char === ']') {
                    depth--;
                    if (depth < 0) return false;
                }
            }
        }
        
        return depth === 0 && !inString && (trimmed[0] === '{' || trimmed[0] === '[');
    }
    
    formatJson(json, indent = 2) {
        if (!this.isValidJson(json)) return "Invalid JSON";
        
        const trimmed = json.trim();
        let result = '';
        let indentLevel = 0;
        let inString = false;
        let escapeNext = false;
        const indentStr = ' '.repeat(indent);
        
        for (let i = 0; i < trimmed.length; i++) {
            const char = trimmed[i];
            
            if (escapeNext) {
                result += char;
                escapeNext = false;
            } else if (char === '\\' && inString) {
                result += char;
                escapeNext = true;
            } else if (char === '"') {
                result += char;
                inString = !inString;
            } else if (!inString) {
                if (char === '{' || char === '[') {
                    result += char;
                    indentLevel++;
                    result += '\n' + indentStr.repeat(indentLevel);
                } else if (char === '}' || char === ']') {
                    indentLevel--;
                    result += '\n' + indentStr.repeat(indentLevel) + char;
                } else if (char === ',') {
                    result += char;
                    result += '\n' + indentStr.repeat(indentLevel);
                } else if (char === ':') {
                    result += char + ' ';
                } else if (!/\s/.test(char)) {
                    result += char;
                }
            } else {
                result += char;
            }
        }
        
        return result;
    }
    
    minifyJson(json) {
        if (!this.isValidJson(json)) return "Invalid JSON";
        
        let result = '';
        let inString = false;
        let escapeNext = false;
        
        for (let char of json) {
            if (escapeNext) {
                result += char;
                escapeNext = false;
            } else if (char === '\\' && inString) {
                result += char;
                escapeNext = true;
            } else if (char === '"') {
                result += char;
                inString = !inString;
            } else if (!inString && /\s/.test(char)) {
                // 忽略空格
            } else {
                result += char;
            }
        }
        
        return result;
    }
    
    getJsonValue(json, path) {
        if (!this.isValidJson(json)) return "Invalid JSON";
        
        const parts = path.split('.');
        let current = json.trim();
        
        for (let part of parts) {
            if (!part) continue;
            
            if (part.includes('[')) {
                const fieldName = part.substring(0, part.indexOf('['));
                const index = parseInt(part.match(/\[(\d+)\]/)[1]) || 0;
                
                const pattern = new RegExp(`"${fieldName}"\\s*:\\s*\\[(.*?)\\]`);
                const match = current.match(pattern);
                if (match) {
                    const arrayContent = match[1];
                    const elements = arrayContent.split(',').map(e => e.trim());
                    current = index < elements.length ? elements[index] : 'null';
                } else {
                    current = 'null';
                }
            } else {
                const pattern = new RegExp(`"${part}"\\s*:\\s*([^,}\\]]+)`);
                const match = current.match(pattern);
                current = match ? match[1].trim() : 'null';
            }
        }
        
        return current;
    }
    
    mergeJson(json1, json2) {
        if (!this.isValidJson(json1) || !this.isValidJson(json2)) {
            return "Invalid JSON";
        }
        
        let trimmed1 = json1.trim();
        let trimmed2 = json2.trim();
        
        trimmed1 = trimmed1.substring(1, trimmed1.length - 1);
        trimmed2 = trimmed2.substring(1, trimmed2.length - 1);
        
        let merged;
        if (trimmed1.length === 0) {
            merged = trimmed2;
        } else if (trimmed2.length === 0) {
            merged = trimmed1;
        } else {
            merged = trimmed1 + ',' + trimmed2;
        }
        
        return '{' + merged + '}';
    }
    
    analyzeJson(json) {
        if (!this.isValidJson(json)) {
            return { valid: false, error: 'Invalid JSON format' };
        }
        
        const trimmed = json.trim();
        let objectCount = 0;
        let arrayCount = 0;
        let stringCount = 0;
        let numberCount = 0;
        let inString = false;
        let escapeNext = false;
        
        for (let char of trimmed) {
            if (escapeNext) {
                escapeNext = false;
            } else if (char === '\\' && inString) {
                escapeNext = true;
            } else if (char === '"') {
                inString = !inString;
                if (inString) stringCount++;
            } else if (!inString) {
                if (char === '{') objectCount++;
                else if (char === '[') arrayCount++;
                else if (/[0-9-]/.test(char)) numberCount++;
            }
        }
        
        return {
            valid: true,
            type: trimmed[0] === '{' ? 'Object' : 'Array',
            objects: objectCount,
            arrays: arrayCount,
            strings: stringCount,
            size: trimmed.length
        };
    }
}

// 使用示例
const tool = new JsonFormatterValidator();
const json = '{"name":"John","age":30,"city":"New York"}';

console.log("原始 JSON:", json);
console.log("验证结果:", tool.isValidJson(json));
console.log("格式化后:\n", tool.formatJson(json));
console.log("压缩后:", tool.minifyJson(json));
console.log("查询 name:", tool.getJsonValue(json, "name"));
console.log("分析结果:", tool.analyzeJson(json));

JavaScript 代码说明: JavaScript 版本是 Kotlin 代码的直接转译。由于 JavaScript 和 Kotlin 在语法上有差异,我们需要进行相应的调整。例如,Kotlin 的 String.repeat() 在 JavaScript 中也有对应的方法。Kotlin 的正则表达式在 JavaScript 中使用 RegExp 对象。整体逻辑和算法与 Kotlin 版本保持一致,确保跨平台的一致性。


ArkTS 调用代码

// JsonFormatterPage.ets
import { JsonFormatterValidator } from './JsonFormatterValidator';

@Entry
@Component
struct JsonFormatterPage {
    @State jsonInput: string = '{"name":"John","age":30,"city":"New York"}';
    @State jsonOutput: string = '';
    @State selectedMode: string = 'format';
    @State validationResult: string = '';
    @State analysisResult: string = '';
    @State queryPath: string = '';
    @State queryResult: string = '';
    
    private tool: JsonFormatterValidator = new JsonFormatterValidator();
    
    processJson() {
        try {
            const isValid = this.tool.isValidJson(this.jsonInput);
            this.validationResult = isValid ? '✓ JSON 格式正确' : '✗ JSON 格式错误';
            
            if (!isValid) {
                this.jsonOutput = '无效的 JSON 格式';
                return;
            }
            
            switch (this.selectedMode) {
                case 'format':
                    this.jsonOutput = this.tool.formatJson(this.jsonInput, 2);
                    break;
                case 'minify':
                    this.jsonOutput = this.tool.minifyJson(this.jsonInput);
                    break;
                case 'analyze':
                    const analysis = this.tool.analyzeJson(this.jsonInput);
                    this.jsonOutput = JSON.stringify(analysis, null, 2);
                    this.analysisResult = `类型: ${analysis.type}, 对象数: ${analysis.objects}, 数组数: ${analysis.arrays}, 大小: ${analysis.size} 字节`;
                    break;
            }
        } catch (error) {
            AlertDialog.show({
                message: 'JSON 处理失败: ' + error.message
            });
        }
    }
    
    queryJson() {
        try {
            if (this.queryPath.trim().length === 0) {
                AlertDialog.show({
                    message: '请输入查询路径'
                });
                return;
            }
            
            this.queryResult = this.tool.getJsonValue(this.jsonInput, this.queryPath);
        } catch (error) {
            AlertDialog.show({
                message: '查询失败: ' + error.message
            });
        }
    }
    
    build() {
        Column() {
            Text('JSON 格式化和验证工具')
                .fontSize(24)
                .fontWeight(FontWeight.Bold)
                .margin({ top: 20, bottom: 20 })
            
            // 模式选择
            Row() {
                Text('处理模式:')
                    .fontSize(14)
                    .margin({ right: 10 })
                
                Select([
                    { value: '格式化', text: 'format' },
                    { value: '压缩', text: 'minify' },
                    { value: '分析', text: 'analyze' }
                ])
                    .value(this.selectedMode)
                    .onSelect((index: number, value?: string) => {
                        this.selectedMode = value || 'format';
                    })
            }
            .margin({ bottom: 15 })
            .width('100%')
            
            // JSON 输入框
            TextArea({ placeholder: '输入 JSON 数据' })
                .value(this.jsonInput)
                .onChange((value: string) => {
                    this.jsonInput = value;
                })
                .height(150)
                .margin({ bottom: 15 })
                .padding(10)
                .border({ width: 1, color: '#cccccc' })
            
            // 验证结果
            if (this.validationResult.length > 0) {
                Text(this.validationResult)
                    .fontSize(12)
                    .fontColor(this.validationResult.includes('✓') ? '#52c41a' : '#ff6b6b')
                    .margin({ bottom: 10 })
            }
            
            // 处理按钮
            Button('处理')
                .width('100%')
                .height(40)
                .margin({ bottom: 10 })
                .onClick(() => {
                    this.processJson();
                })
            
            // 输出框
            if (this.jsonOutput.length > 0) {
                Column() {
                    Text('处理结果:')
                        .fontSize(14)
                        .fontWeight(FontWeight.Bold)
                        .margin({ bottom: 10 })
                    
                    TextArea()
                        .value(this.jsonOutput)
                        .enabled(false)
                        .height(150)
                        .padding(10)
                        .backgroundColor('#f5f5f5')
                        .border({ width: 1, color: '#cccccc' })
                }
                .width('100%')
                .margin({ bottom: 15 })
            }
            
            // 分析结果
            if (this.analysisResult.length > 0) {
                Text(this.analysisResult)
                    .fontSize(12)
                    .fontColor('#666666')
                    .margin({ bottom: 15 })
            }
            
            // 查询功能
            Column() {
                Text('JSON 路径查询')
                    .fontSize(14)
                    .fontWeight(FontWeight.Bold)
                    .margin({ bottom: 10 })
                
                Row() {
                    TextInput({ placeholder: '输入路径,如: name 或 items[0]' })
                        .value(this.queryPath)
                        .onChange((value: string) => {
                            this.queryPath = value;
                        })
                        .flex(1)
                        .padding(10)
                        .border({ width: 1, color: '#cccccc' })
                    
                    Button('查询')
                        .width(60)
                        .height(40)
                        .margin({ left: 10 })
                        .onClick(() => {
                            this.queryJson();
                        })
                }
                .margin({ bottom: 10 })
                
                if (this.queryResult.length > 0) {
                    Column() {
                        Text('查询结果:')
                            .fontSize(12)
                            .fontColor('#666666')
                            .margin({ bottom: 5 })
                        
                        Text(this.queryResult)
                            .fontSize(12)
                            .selectable(true)
                            .padding(10)
                            .backgroundColor('#f5f5f5')
                            .borderRadius(4)
                    }
                    .width('100%')
                }
            }
            .width('100%')
            .padding(10)
            .backgroundColor('#fafafa')
            .borderRadius(4)
        }
        .padding(20)
        .width('100%')
        .height('100%')
        .backgroundColor('#ffffff')
        .scrollable(true)
    }
}

ArkTS 代码说明: 这个示例展示了如何在 ArkTS 中构建一个完整的 JSON 处理用户界面。页面包含了模式选择、JSON 输入框、验证结果显示、处理按钮、输出框、分析结果和路径查询等组件。用户可以输入 JSON 数据,选择处理模式(格式化、压缩或分析),然后点击处理按钮查看结果。此外,页面还提供了路径查询功能,允许用户快速提取 JSON 中的特定值。


实战案例

案例 1: API 响应处理

在开发移动应用时,经常需要处理来自 API 的 JSON 响应。使用 JSON 工具可以快速验证响应的合法性,并提取所需的数据。

val tool = JsonFormatterValidator()
val apiResponse = """{"status":"success","data":{"userId":123,"userName":"John"}}"""

if (tool.isValidJson(apiResponse)) {
    val userId = tool.getJsonValue(apiResponse, "data.userId")
    val userName = tool.getJsonValue(apiResponse, "data.userName")
    println("用户 ID: $userId, 用户名: $userName")
}

案例 2: 配置文件验证

在应用启动时,需要验证配置文件的合法性。使用 JSON 工具可以确保配置文件的格式正确。

val tool = JsonFormatterValidator()
val configJson = readConfigFile()

if (tool.isValidJson(configJson)) {
    val analysis = tool.analyzeJson(configJson)
    println("配置文件分析: $analysis")
} else {
    println("配置文件格式错误,请检查")
}

案例 3: 日志数据分析

在分析日志数据时,经常需要处理 JSON 格式的日志。使用 JSON 工具可以快速格式化和分析日志数据。

val tool = JsonFormatterValidator()
val logJson = """{"timestamp":"2024-01-01T10:00:00","level":"INFO","message":"User login"}"""

val formatted = tool.formatJson(logJson)
println("格式化后的日志:\n$formatted")

val minified = tool.minifyJson(logJson)
println("压缩后的日志: $minified")

最佳实践

1. 验证优先

  • 总是验证 JSON:在处理 JSON 前,先验证其合法性
  • 提供错误信息:验证失败时提供详细的错误信息
  • 处理异常:使用 try-catch 处理可能的异常

2. 性能优化

  • 缓存验证结果:对于频繁使用的 JSON,缓存验证结果
  • 流式处理:对于大型 JSON,使用流式处理而不是一次性加载
  • 异步处理:对于耗时的 JSON 操作,使用异步处理

3. 安全考虑

  • 防止注入攻击:验证 JSON 中的数据,防止恶意输入
  • 限制递归深度:防止深层嵌套导致的栈溢出
  • 验证数据类型:确保 JSON 中的数据类型符合预期

4. 用户体验

  • 实时反馈:提供实时的验证和处理反馈
  • 清晰的错误提示:错误发生时提供清晰的错误信息
  • 支持多种操作:提供格式化、压缩、查询等多种操作

5. 可维护性

  • 模块化设计:将不同的功能分解为独立的方法
  • 充分的注释:为复杂的算法添加详细的注释
  • 单元测试:编写单元测试确保功能的正确性

总结

JSON 格式化和验证工具是现代应用开发中的一个重要组件。通过使用 Kotlin Multiplatform,我们可以编写一次代码,然后在多个平台上运行,大大提高了开发效率和代码的可维护性。这个案例展示了如何实现 JSON 验证、格式化、压缩、查询和分析等功能。

在实际应用中,应该根据具体的需求选择合适的 JSON 处理方式,并遵循最佳实践来确保数据的准确性和安全性。同时,应该定期进行测试和优化,以提高应用的性能和用户体验。通过合理使用 JSON 工具,我们可以更加高效地处理和分析数据,提高应用的质量和可靠性。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐