【鸿蒙生态共建】一文说清复杂类型数据的非预期输入转换与兜底-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利

作者:俩毛豆日期:2025/10/7

在客户端开发中,你是否曾遇到过这样的困扰:一次看似寻常的网络数据解析,却导致了出人意料的崩溃;一个本该正常的文件读取操作,却返回了难以理解的数据错误。这些问题的根源,往往指向同一环节——数据类型转换。当应用面对网络传输、文件I/O等不可控的数据源时,如何稳健、准确地进行数据解析与转换,就成为保障应用稳定性的第一道防线。

本篇内容是《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》这本书第四章内容的延续,是咱这本书读者的福利,在本篇内容中以模拟多种数据输入,向复杂类型(类、数组、Record)数据转换的输出,以确定最优的代码编方式,以避免非预期的异常产生,每个示例可以独立的编译及调试,欢迎大家一同来深入的解,甚至可以当作面试题来学习。

建议读者可以先看一下:

【鸿蒙生态共建】一文说清基础类型数据的非预期输入转换与兜底-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利

打个广告,对本书感兴趣的同学可以点击以下链接进行购买,或者了解我的班级参加 班级共同学习,点击链接可进入(华为官方活动)

往期福利:

  1. 【页面路由导航】三步实现页面跳转的完整示例-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利
  2. 【鸿蒙生态共建】一文10个示例讲懂鸿蒙系统ArkTS中的null与undefined的区别与应用-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利
  3. 【鸿蒙生态共建】一文两表三实例讲清async函数与普通函数的区别-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利
  4. 【鸿蒙生态共建】一文说清基础类型数据的非预期输入转换与兜底-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利
  5. 【鸿蒙生态共建】一文说明兼容版本、目标版本和编译版本的区别与应用实践-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利

1: 测试数据准备

在ArkTS中,由于语言的特性,无法直接对明确的类型数据进行直接强转,故先将该不同类型的数据存到Record中,之后再使用。

// 声明一个变量testRecord,其中包含,字符串、类、数组、Record等不同类型的数据,可以通过testRecord获取对应的不同类型数据

// 定义接口 interface Animal { name: string; eat(food: string): void; }

// 类实现接口 class Dog implements Animal { name: string; constructor(name: string) { this.name = name; } eat(food: string) { console.log(${this.name} is eating ${food}); } }

// 类实例 let myDog: Animal = new Dog("八万"); // 起个名叫八万 myDog.eat("肉包子"); // 八万吃个肉包子 let tRecord:Record<string,number> = {"number_key":666}; let tArray:Array<string> = ["str1","str2"]; // Record数据,key是string类型,value是Object类型,当Value支持多种类型时,常见写法 let testRecord:Record<string,Object> = {"str_key":"strValue","array_key":tArray,"class_key":myDog,"record_key":tRecord}; // 或写成多种类型的组合 // let testRecord:Record<string,string | Array<string> | Dog | Record<string,number> > = {"str_key":"strValue", "array_key":tArray,"class_key":myDog,"record_key":tRecord};

2:复杂数据类型的有效性验证问题

在ArkTS语言中,基础数据类型可通过 typeof 来判断(比如 string、number、undefined、null),但是对于复杂的数据类型,typeof该变量的取值为"object",下面的代码分别将Array、类、Record的变量的typeof取值以Log的方式输出。

// Array、类、Record等非基础类型,使用typeof时,结果为 “object”,无法区分 console.log("俩毛豆: typeof testRecord["array_key"] " + typeof testRecord["array_key"]); console.log("俩毛豆: typeof testRecord["class_key"] " + typeof testRecord["class_key"]); console.log("俩毛豆: typeof testRecord["record_key"] " + typeof testRecord["record_key"]);

输出的日志截图如下,typeof取值均为 object,如果仅是对其值是否有值的判断(不为null或不为undefined),会存在数据有效性判断不符合预期的情况。

3: Array类型数据的转换及识别

在ArkTS语言中,可以使用instanceof和Array.isArray来判断某个变量是否为Array类型,如下示例。

if (testRecord["array_key"] instanceof Array) { console.log("俩毛豆: testRecord[array_key] is instanceof Array true"); } else { console.log("俩毛豆: testRecord[array_key] is instanceof Array false"); }

if (Array.isArray(testRecord["array_key"])) { console.log("俩毛豆: Array.isArray(testRecord[array_key]) ture"); } else { console.log("俩毛豆: Array.isArray(testRecord[array_key]) false"); }

if (testRecord["class_key"] instanceof Array) { console.log("俩毛豆: testRecord[class_key] is instanceof Array true"); } else { console.log("俩毛豆: testRecord[class_key] is instanceof Array false"); }

if (testRecord["record_key"] instanceof Array) { console.log("俩毛豆: testRecord[record_key] is instanceof Array true"); } else { console.log("俩毛豆: testRecord[record_key] is instanceof Array false"); }

对应的log输出及编译调试时的变量状态的截图,可以看出,类对象实例和Record变量被判定为非Array。在实际研发过程中,可先对其进行类型的判断,再进行下一步的数据处理即可。

4: Record类型数据的转换及识别

在ArkTS的原生API中没有提供直接判断是否为Record的方法,可以封装一个函数进行基本的判断。下面的示例实现了判定是否为Record的方法,但这种方式,如果是类实例,也会返回 true,如果需要强效验,可以在此基础检查所有key的类型及值,按需定制,在这里不作过多介绍。

function isRecord(obj: Object): boolean { // 检查是否为object 且 非null/undefine的数组 // 这种方式,如果是类实例,也会返回 true if (typeof obj !== 'object' || obj === null || obj === undefined || Array.isArray(obj)) { return false; } return true; }

对应的验证示例

if (isRecord(testRecord["array_key"])) { console.log("俩毛豆: testRecord[array_key] is Record true"); } else { console.log("俩毛豆: testRecord[array_key] is Record false"); } if (isRecord(testRecord["class_key"])) { console.log("俩毛豆: testRecord[class_key] is Record true"); } else { console.log("俩毛豆: testRecord[class_key] is Record false"); } if (isRecord(testRecord["record_key"])) { console.log("俩毛豆: testRecord[record_key] is Record true"); } else { console.log("俩毛豆: testRecord[record_key] is Record false"); }

对应的log输出的截图,可以看出,类对象实例和Record,结果判断均为true,这时需要对实际的Record中记录的key及Value进行判断

4.1 类对象实例与Record的互转

如果对类对象实例进行Record的取值操作,得到的结果是什么呢?下面分别将类对象实例及Record变量进行取值操作。

let classObjAsRecord:Record<"string",Object> = testRecord["class_key"] as Record<"string",Object>; let recordObjAsRecord:Record<"string",Object> = testRecord["record_key"] as Record<"string",Object>; console.log("俩毛豆: classObjAsRecord[number_key] = " + classObjAsRecord["number_key"]); console.log("俩毛豆: recordObjAsRecord[number_key] = " + recordObjAsRecord["number_key"]);

对应的执行结果Log如下截图,可以看出,当对类对像进行Record的取值操作时,该值为undefined,并没有产生异常。也就是说对于Record变量进行取值,进行二次效验是有必要且可行。

5: 类实例的转换及识别

在ArkTS语言中,可以使用instanceof来判断某个变量是否为某个类,如下示例,分别判断不同类的类型是否为Dog类。

// instanceof array_key if (testRecord["array_key"] instanceof Dog) { console.log("俩毛豆: testRecord[array_key] is instanceof Dog true"); } else { console.log("俩毛豆: testRecord[array_key] is instanceof Dog false"); } // instanceof class_key if (testRecord["class_key"] instanceof Dog) { console.log("俩毛豆: testRecord[class_key] is instanceof Dog true"); } else { console.log("俩毛豆: testRecord[class_key] is instanceof Dog false"); } // instanceof record_key if (testRecord["record_key"] instanceof Dog) { console.log("俩毛豆: testRecord[record_key] is instanceof Dog true"); } else { console.log("俩毛豆: testRecord[record_key] is instanceof Dog false"); }

对应的log输出的截图,可以看出,这种方式的判定是有效的。

5.1 接口类的识别

在实际的研发工作中,一些场景需要判定某个类对象实例是否属于实现某个接口类,之后再进行接口的调用。如果类对象实例没有实现该接口,直接进行调用,则会出现异常。

let recordObjAsClass:Animal = testRecord["record_key"] as Animal; recordObjAsClass.eat("骨头")

如下图所示,错误的原因为类型错误,不可调用。

接口类的判定,在ArkTS语言中没有基础的API为研发人员使用,可以按下思路实现判定的函数。 假设我们不确定某个变量是否实现了 Animal(第1小节中有介绍) 接口, 可以检查是类实例对象否存在接口中定义的必需属性和方法,并验证类型即可。下面为代码示例

function isAnimalInterface(obj: Animal) { return obj && typeof obj.name === 'string' && typeof obj.eat === 'function'; } if (isAnimalInterface(recordObjAsClass)) { recordObjAsClass.eat("骨头"); } else { console.log("俩毛豆:recordObjAsClass 没有实现 Animal接口"); }

对应的执行Log输出截图如下,可以看出,对是否实现于接口类的判定,可以使用上述的方法。实际运行时,obj.name和obj.eat是undefined。比较有经验的同学们,会用可选链操作符如 recordObjAsClass.eat?.("骨头"),这种写法也可以规避异常的产生。

总结:

在本篇的内容中基于HarmonyOS开发中复杂数据类型的转换问题展开,目标是有效的、稳定的使用数据,并针对ArkTS语言中Array、Record和类实例的识别与转换提供了实用解决方案。这些技术点不仅是开发中的常见痛点,也可作为面试考察内容,为HarmonyOS开发者提供了解决数据类型转换问题的系统性思路。

最后再打下广告,对本书感兴趣的同学可以点击以下链接进行购买,或者了解我的班级参加 班级共同学习,点击链接可进入(华为官方活动)


【鸿蒙生态共建】一文说清复杂类型数据的非预期输入转换与兜底-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利》 是转载文章,点击查看原文


相关推荐


Spring Cloud之负载均衡之LoadBalance
新绿MEHO2025/10/6

目录 负载均衡 问题 步骤 现象  什么是负载均衡? 负载均衡的一些实现 服务端负载均衡 客户端负载均衡 使用Spring Cloud LoadBalance实现负载均衡 负载均衡策略 ​编辑 ​编辑LoadBalancer原理 服务部署 准备环境和数据 服务构建打包 启动服务 上传Jar包到云服务器 启动服务 远程调用访问  负载均衡 问题 上面是我们之前的代码,是根据应用名称获取了服务实例列表,并从列表中选择了一个服务实例。 那如果


Qwen3 Omni 的“全模态”,到底和多模态有啥不一样?
飞哥数智谈2025/10/5

前一阵阿里云栖大会,其中有个发布内容是全模态大模型 Qwen3-Omni。 说实话,这是我第一次真正地审视“全模态大模型”这个概念,因为之前 Qwen2.5-Omni 发布的时候,有了解过,但不多。 简介 先从概念上简单介绍下什么是“全模态大模型”。 “Qwen3-Omni是新一代原生全模态大模型,能够无缝处理文本、图像、音频和视频等多种输入形式,并通过实时流式响应同时生成文本与自然语音输出。” 多模态大模型 vs 全模态大模型 接下来,为了更好地理解,我们与“多模态大模型”做个对比。 相同点是


【算法导论】PDD 0928 笔试题解
PAK向日葵2025/10/4

快递单号 多多在快递公司负责快递单号录入工作,这些单号有严格的格式要求: 快递单号由3部分组成:2位大写字母(A~Z) + 6位数字 + 1位校验位 校验位计算规则:取前8位(2 字母 + 6 数字)中每个字符的ASCII码之和,对26取余后,加上A的ASCII码,得到的字符即为校验位 现在有一批可能存在校验位错误的单号,请你编写程序: 若单号格式正确且校验位正确,返回原单号 若前 8 位格式正确但校验位错误,返回修复后(校正校验位)的单号 若前 8 位格式错误(非 2 字母 + 6 数字)或


chrome-devtools-mcp windows 环境安装
monkeySix2025/10/2

问题: Could not find Google Chrome executable for channel 'stable' at 'C:\Program Files\Google\Chrome\Application\chrome.exe'. 解决方案: "chrome-devtools": { "command": "npx", "args": [ "chrome-devtools-mcp@latest", "-


C语言趣味小游戏----猜数字小游戏
雨落在了我的手上2025/10/2

一:猜数字游戏的雏形 部分代码如下,这下面的代码只是一个初步的框架,还不能正式的进行猜数字游戏,因为我还没有将猜数字的代码写进去,这里我先给大家解释一下是下面代码的大致意思 首先呢这个猜数字游戏我们要运用do while循环以及switch语句来初步的进行我们的猜数字游戏,当然我们可以不用do while循环,可以用while循环还有就是 for循环,但是这里我推荐大家用do while循环,因为会更加的好理解以及使用 现在我分别拆开代码来和大家一一介绍 int main() { in


Python 的内置函数 aiter
IMPYLH2025/10/2

Python 内建函数列表 > Python 的内置函数 aiter 你是否曾经在异步编程中处理过异步迭代器(Async Iterators)?是否对 async for 循环背后的机制感到好奇?那么,aiter() 就是 Python 提供的一个关键工具,它允许我们更灵活地处理异步可迭代对象(Async Iterables)。 aiter 的函数原型如下: def aiter(async_iterable): ''' 获取异步可迭代对象的迭代器 :param a


改bug的一些体会
花王江不语10/1/2025

这篇摘要总结了代码调试的实用技巧:1)通过构造函数断点快速了解类使用方式;2)代码比对时重点关注首次差异点;3)不熟悉代码时先寻找正确案例对比;4)调试和日志要灵活运用,循环场景适合日志,测试机问题可通过动态库加日志解决;5)平衡调试与代码阅读,以理解代码为目的;6)始终围绕线索展开分析,避免偏离核心问题。这些方法强调务实、聚焦和工具选择的灵活性,帮助开发者高效定位和解决问题。


【开题答辩全过程】以 SpringBootVue的旅游租车管理系统为例,包含答辩的问题和答案
毕设源码-钟学长9/30/2025

这是一篇关于毕业设计答辩的纪实内容,主要记录了&quot;基于SpringBoot+Vue的旅游租车管理系统&quot;的答辩过程。答辩学生详细介绍了系统功能(租车+旅游推荐)、技术架构(SpringBoot+Vue+MySQL)和关键实现(库存控制、登录认证等)。评委老师针对系统设计、数据一致性、推荐算法等提出专业问题,学生给出了具体的技术解决方案。最后评委肯定选题价值和技术实现,建议完善旅游信息模块。文末提供开题报告参考和毕设指导服务,适合处于开题阶段的学生参考使用。全文突出了系统设计细节和答辩应对技巧


Seata分布式事务框架详解与项目实战
IT橘子皮2025/10/9

一、Seata核心架构与原理 Seata(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的分布式事务解决方案,旨在为微服务架构提供高性能、易用性的分布式事务支持。其核心设计理念是"化繁为简",通过封装传统分布式事务模式的复杂性,降低分布式一致性问题的解决门槛。 ​核心组件​: ​TC(Transaction Coordinator)​​:事务协调者,维护全局事务和分支事务的状态,负责协调全局事务提交或回滚 ​TM(


我用亲身经历告诉你,为什么程序员千万别不把英语当回事
oioihoii2025/10/10

年轻人,如果你现在觉得写代码只需要认识 if/else 和 for 循环里的那几个英文单词就够了,那你简直像极了十年前的我。而今天的我,多想回到过去,给那个骄傲自满的自己一记响亮的耳光。 我不是以成功者的姿态来教导你,而是以一个踩过坑、吃过亏、肠子都悔青了的过来人身份,跟你聊聊我最后悔的一件事——没有早点学好英语。 一、工作里吃的哑巴亏,都是我当年脑子进的水 1. “啃”二手资料的酸楚 还记得那次,团队要引入一个热门的新框架。我兴冲冲地找了几篇中文博客,照猫画虎地搞了起来。结果,掉进了一个坑里,

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0