dly_blog 2025-09-12 10:26:19 我需要读取 JSON 配置文件并校验字段是否完整,否则报错。请问在HarmonyOS开发时,如何实现 JSON 的读取与字段检查?
```ts
const cfg = JSON.parse(fs.readFileSync(path).toString());
if (!cfg.url || !cfg.token) throw new Error('invalid config');
```
| 步骤 | 关键动作 | HarmonyOS/ArkTS 中的主要工具 |
|---|---|---|
| 1. 放置 JSON 文件 | 将配置文件放入 resources/rawfile 目录 |
DevEco Studio 项目结构 |
| 2. 读取文件内容 | 同步或异步读取 rawfile 中的文件 |
resourceManager.getRawFileContentSync()1 |
| 3. 解析 JSON | 将读取的字符串解析为 JavaScript 对象 | JSON.parse() |
| 4. 校验字段 | 检查必需字段是否存在且符合预期 | 条件判断 + 类型检查 |
| 5. 错误处理 | 优雅地处理文件不存在、解析失败、字段缺失等异常 | try...catch |
1. 放置 JSON 配置文件
首先,将你的 JSON 配置文件(例如 config.json)放在项目的 resources/rawfile 目录下。这是 HarmonyOS 应用存放原始资源文件的推荐位置。
一个示例的 config.json 内容如下:
{
"url": "https://api.example.com/data",
"token": "my-secret-token-123",
"timeout": 5000,
"retryCount": 3
}
2. 读取并解析 JSON 文件
在 ArkTS 中,你可以使用 resourceManager 来读取 rawfile 目录下的文件内容。
import { util } from '@kit.ArkTS'; // 用于 TextDecoder
// 1. 定义一个配置接口来明确期望的数据结构
interface AppConfig {
url: string;
token: string;
timeout?: number; // 可选字段
retryCount?: number; // 可选字段
}
class ConfigManager {
// 2. 读取并解析配置的核心方法
async loadConfig(): Promise<AppConfig> {
try {
const context = getContext(this) as common.Context;
// 3. 同步读取 rawfile 目录下的 config.json 文件,返回 Uint8Array 数据:cite[1]
const uint8Array = context.resourceManager.getRawFileContentSync('config.json');
// 4. 使用 TextDecoder 将 Uint8Array 解码为字符串:cite[1]
const textDecoder = new util.TextDecoder();
const jsonStr = textDecoder.decodeToString(uint8Array);
// 5. 将 JSON 字符串解析为 JavaScript 对象
const config: AppConfig = JSON.parse(jsonStr);
// 6. 校验必需的字段
this.validateConfig(config);
return config;
} catch (error) {
// 统一处理可能出现的异常(文件不存在、JSON 解析错误、字段验证失败等)
console.error('Failed to load config:', error.message);
throw new Error(`Configuration error: ${error.message}`);
}
}
// 7. 校验字段完整性的方法
private validateConfig(config: AppConfig): void {
// 检查必需的字符串字段是否存在且不为空
if (!config.url || typeof config.url !== 'string' || config.url.trim() === '') {
throw new Error('Missing or invalid required field: url');
}
if (!config.token || typeof config.token !== 'string' || config.token.trim() === '') {
throw new Error('Missing or invalid required field: token');
}
// 如果有可选字段,可以设置默认值
if (config.timeout === undefined || config.timeout < 0) {
config.timeout = 5000; // 默认超时时间
}
if (config.retryCount === undefined || config.retryCount < 0) {
config.retryCount = 3; // 默认重试次数
}
// 这里可以添加更多自定义验证,比如 URL 格式验证等
if (!config.url.startsWith('http://') && !config.url.startsWith('https://')) {
throw new Error('Invalid url format, must start with http:// or https://');
}
}
}
3. 在应用中使用配置
在你的 UI 组件或业务逻辑中,可以这样使用 ConfigManager:
@Entry
@Component
struct MyApp {
private configManager: ConfigManager = new ConfigManager();
@State config: AppConfig | null = null;
@State errorMessage: string = '';
aboutToAppear() {
this.loadConfig();
}
async loadConfig() {
try {
this.config = await this.configManager.loadConfig();
console.log('Config loaded successfully:', this.config);
// 配置加载成功,可以开始你的应用逻辑了
} catch (error) {
this.errorMessage = error.message;
// 这里可以根据错误类型向用户显示友好的错误信息
}
}
build() {
Column() {
if (this.errorMessage) {
// 显示错误信息
Text(`Config Error: ${this.errorMessage}`)
.fontSize(18)
.fontColor(Color.Red)
.margin(10);
Button('Retry') {
this.errorMessage = '';
this.loadConfig();
}
.margin(10)
} else if (this.config) {
// 正常显示应用界面
Text('App Loaded Successfully')
.fontSize(20)
.margin(10);
// ... 其他界面组件
} else {
// 显示加载中
Progress()
.width(50)
.height(50);
Text('Loading Configuration...')
.margin(10);
}
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
4. 处理大 JSON 文件
如果你的 JSON 文件很大(例如用户提到的 30000 多行),一次性读取整个文件可能会遇到性能问题。这时可以考虑以下策略:
流式处理:如果文件非常大,可以考虑使用 getRawFd 获取文件描述符,然后分块读取和处理文件。
数据拆分:考虑是否可以将一个大配置文件拆分为多个小文件,按需加载。
5. 错误处理的最佳实践
健全的错误处理机制能让你的应用更稳定:
具体错误信息:区分是文件不存在、JSON 格式错误还是字段缺失,并给出明确的错误提示。
降级方案:某些配置字段缺失时,可以考虑使用合理的默认值而不是直接报错。
用户提示:向用户展示友好的错误信息,而不是原始的异常信息。
6. 补充说明
关于 rawfile 和 resfile:请注意 resources/rawfile 目录下的文件在应用安装后不会被自动解压到沙箱目录,需要通过 resourceManager.getRawFileContentSync() 或 getRawFileContent() 方法访问。而 resources/base/element 等目录下的资源文件访问方式可能不同。
异步读取:上面的例子使用了同步方法 getRawFileContentSync, HarmonyOS 也提供了异步版本 getRawFileContent,你可以根据需要选择。