OpenHarmony的ArkTS如何进行JSON字符串的解析工作
目录
引言
出错现象
代码示例
结语
引言
最近在使用OpenHarmony 4.1的ArkTS在做物联网测试,其中一项工作就是对华为IoTDA发来的JSON数据进行解析。本来以为是个简单的工作,但是豆包和Kimi生成的代码在DevEco Studio 4.1下都不能工作。于是对这个问题研究了一下,终于找到了能工作的代码。
出错现象
我问了Kimi一个问题:
在arkts中,收到的mqtt payload为{"services": [{"serviceId": "smarthome", "properties": {"温度":20, "湿度":20,"LED状态": "ON"}}]},请问怎么解析出其中的LED状态
Kimi给出的示例代码是这样的:
// 假设 payload 是从 MQTT 消息中接收到的 JSON 字符串
const payload = '{"services": [{"serviceId": "smarthome", "properties": {"温度":20, "湿度":20,"LED状态": "ON"}}]}';
// 使用 JSON.parse 将字符串解析为对象
const payloadObject = JSON.parse(payload);
// 提取 LED 状态
const ledStatus = payloadObject.services[0].properties["LED状态"];
// 打印 LED 状态
console.log("LED 状态:", ledStatus);
豆包给出的代码也差不多。这段代码在DevEco Studio 4.1中会遇到错误:
Use explicit types instead of “any“, “unknown“ (arkts-no-any-unknown) <ArkTSCheck>
这个提示意思是建议在代码中避免使用 any
和 unknown
类型,而是使用更明确的具体类型。 在TypeScript中JSON.parse返回的是any类型,虽然ArkTS和TypeScript差不多,但是在ArkTS中不能这么做了。
要解决这个问题,就需要先定义解析后的类型,类型中的字段名和JSON中的字段名一一对应,然后在讲parse解析后的对象指定为自定义的类型。
代码示例
针对这个问题,我对Kimi和豆包都使用了下面的提示词:
在arkts中如何解析json对象,考虑到arkts严格检查对象,不支持any和undefined
两者都改变了生成的代码,都更接近最终结果,但是也都有错误。豆包的生成更接近一些,下面的代码也是从豆包改过来的:
根据 JSON 数据的结构,我们需要定义几个类来描述其类型,具体包括 Service
类和 DeviceProperties
类,同时为整个数据定义一个包含 services
数组的结构。通过 JSON.parse
方法将 JSON 字符串转换为 JavaScript 对象,然后把它转换为我们定义的类型。
// 定义设备属性类
class DeviceProperties {
温度: number;
湿度: number;
LED状态: string;
constructor(温度: number, 湿度: number, LED状态: string) {
this.温度 = 温度;
this.湿度 = 湿度;
this.LED状态 = LED状态;
}
}
// 定义服务类
class Service {
serviceId: string;
properties: DeviceProperties;
constructor(serviceId: string, properties: DeviceProperties) {
this.serviceId = serviceId;
this.properties = properties;
}
}
// 定义整个数据结构类
class ServiceData {
services: Service[];
constructor(services: Service[]) {
this.services = services;
}
}
// JSON 字符串
const jsonString = `{"services": [{"serviceId": "smarthome", "properties": {"温度":20, "湿度":20,"LED状态": "ON"}}]}`;
try {
// 解析 JSON 字符串
const parsedData: ServiceData = JSON.parse(jsonString);
// 打印结果
console.log(`Service ID: ${parsedData.services[0].serviceId}`);
console.log(`温度: ${parsedData.services[0].properties.温度}`);
console.log(`湿度: ${parsedData.services[0].properties.湿度}`);
console.log(`LED状态: ${parsedData.services[0].properties.LED状态}`);
} catch (error) {
console.error('JSON 解析失败:', error);
}
豆包生成了正确的数据类型,但是测试代码错了,它解析后由开始编码,输出的是一个编解码混合测试程序,有点混乱。Kimi的思路正确,但是生成的数据类型有错误。
后来,我又用DeepSeek 对这个问题做了回答,在不告诉它ArkTS不允许使用any类型的情况下,它生成了基本正确的代码。看来它要比前面两个确实强一些。但是它生成的代码也有小错误,需要修改才行。
不过它说由于存在中文键名,不能用点符号(obj.properties.LED状态会报语法错误),因此DS建议我将键名改为英文(如ledState
),避免中文键名带来的编码和维护问题。这点是不正确的,因为在ArkTS中可以定义中文字段名。
结语
华为的ArkTS虽然脱胎于TypeScript,但是其有些用法比较特殊,相关的资料还非常匮乏,大模型也不见得能处理对。不过现在大模型演进非常快,春节前,豆包还认为ArkTS是拼写错误呢,现在已经可以正确识别了。估计过段时间,大模型就能正确处理ArkTS的JSON解析问题了。