HarmonyOS鸿蒙Next中怎样处理应用中的JSON数据?

HarmonyOS鸿蒙Next中怎样处理应用中的JSON数据? 开发中需要处理JSON数据,怎样处理:

  • 网络请求返回JSON
  • 本地数据存储
  • 对象与JSON互转
  • 类型安全处理
4 回复

一看就懂

更多关于HarmonyOS鸿蒙Next中怎样处理应用中的JSON数据?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


实现方案

1. 基础JSON操作

/**
 * JSON序列化与反序列化
 */
export class JsonUtils {
  /**
   * 对象转JSON字符串
   */
  static stringify(obj: Object): string {
    return JSON.stringify(obj);
  }
  
  /**
   * JSON字符串转对象
   */
  static parse<T>(json: string): T {
    return JSON.parse(json) as T;
  }
  
  /**
   * 安全解析(带错误处理)
   */
  static safeParse<T>(json: string, defaultValue: T): T {
    try {
      return JSON.parse(json) as T;
    } catch (err) {
      Logger.error('JsonUtils', 'JSON解析失败', err as Error);
      return defaultValue;
    }
  }
  
  /**
   * 格式化JSON(美化输出)
   */
  static format(obj: Object): string {
    return JSON.stringify(obj, null, 2);
  }
}

// ✅ 使用示例
const item = { id: 1, name: '物品1' };
const json = JsonUtils.stringify(item);
const obj = JsonUtils.parse<Item>(json);

2. 模型类定义

/**
 * 物品模型
 */
export class Item {
  id: number = 0;
  name: string = '';
  categoryId: number = 0;
  createTime: number = 0;
  tags: string[] = [];
  
  /**
   * 从JSON创建对象
   */
  static fromJson(json: Record<string, Object>): Item {
    const item = new Item();
    item.id = json.id as number;
    item.name = json.name as string;
    item.categoryId = json.category_id as number;  // 字段映射
    item.createTime = json.create_time as number;
    item.tags = json.tags as string[] || [];
    return item;
  }
  
  /**
   * 转换为JSON对象
   */
  toJson(): Record<string, Object> {
    return {
      id: this.id,
      name: this.name,
      category_id: this.categoryId,  // 字段映射
      create_time: this.createTime,
      tags: this.tags
    };
  }
  
  /**
   * 转换为JSON字符串
   */
  toJsonString(): string {
    return JSON.stringify(this.toJson());
  }
}

// ✅ 使用
const jsonStr = '{"id":1,"name":"物品1","category_id":2,"create_time":1702886400000}';
const item = Item.fromJson(JSON.parse(jsonStr));
console.info('物品:', item.name);

const json = item.toJsonString();
console.info('JSON:', json);

3. 列表数据处理

/**
 * 列表数据转换
 */
export class ItemListConverter {
  /**
   * JSON数组转对象数组
   */
  static fromJsonArray(jsonArray: Array<Record<string, Object>>): Item[] {
    return jsonArray.map(json => Item.fromJson(json));
  }
  
  /**
   * 对象数组转JSON数组
   */
  static toJsonArray(items: Item[]): Array<Record<string, Object>> {
    return items.map(item => item.toJson());
  }
  
  /**
   * JSON字符串转对象数组
   */
  static parseArray(jsonStr: string): Item[] {
    try {
      const jsonArray = JSON.parse(jsonStr) as Array<Record<string, Object>>;
      return this.fromJsonArray(jsonArray);
    } catch (err) {
      Logger.error('ItemListConverter', '解析失败', err as Error);
      return [];
    }
  }
}

// ✅ 使用
const jsonStr = '[{"id":1,"name":"物品1"},{"id":2,"name":"物品2"}]';
const items = ItemListConverter.parseArray(jsonStr);
console.info('物品数量:', items.length);

4. 嵌套对象处理

/**
 * 带分类的物品
 */
export class ItemWithCategory {
  id: number = 0;
  name: string = '';
  category: Category | null = null;  // 嵌套对象
  
  static fromJson(json: Record<string, Object>): ItemWithCategory {
    const item = new ItemWithCategory();
    item.id = json.id as number;
    item.name = json.name as string;
    
    // ✅ 处理嵌套对象
    if (json.category) {
      item.category = Category.fromJson(json.category as Record<string, Object>);
    }
    
    return item;
  }
  
  toJson(): Record<string, Object> {
    const json: Record<string, Object> = {
      id: this.id,
      name: this.name
    };
    
    // ✅ 处理嵌套对象
    if (this.category) {
      json.category = this.category.toJson();
    }
    
    return json;
  }
}

export class Category {
  id: number = 0;
  name: string = '';
  
  static fromJson(json: Record<string, Object>): Category {
    const category = new Category();
    category.id = json.id as number;
    category.name = json.name as string;
    return category;
  }
  
  toJson(): Record<string, Object> {
    return {
      id: this.id,
      name: this.name
    };
  }
}

5. Preferences存储JSON

/**
 * 使用Preferences存储对象
 */
export class PreferencesJsonStorage {
  private prefs: preferences.Preferences;
  
  /**
   * 保存对象
   */
  async saveObject<T>(key: string, obj: T): Promise<void> {
    const json = JSON.stringify(obj);
    await this.prefs.put(key, json);
    await this.prefs.flush();
  }
  
  /**
   * 读取对象
   */
  async getObject<T>(key: string, converter: (json: Record<string, Object>) => T): Promise<T | null> {
    const json = await this.prefs.get(key, '') as string;
    if (!json) {
      return null;
    }
    
    try {
      const obj = JSON.parse(json) as Record<string, Object>;
      return converter(obj);
    } catch (err) {
      Logger.error('PreferencesJsonStorage', '解析失败', err as Error);
      return null;
    }
  }
  
  /**
   * 保存数组
   */
  async saveArray<T>(key: string, array: T[]): Promise<void> {
    const json = JSON.stringify(array);
    await this.prefs.put(key, json);
    await this.prefs.flush();
  }
  
  /**
   * 读取数组
   */
  async getArray<T>(key: string, converter: (json: Record<string, Object>) => T): Promise<T[]> {
    const json = await this.prefs.get(key, '') as string;
    if (!json) {
      return [];
    }
    
    try {
      const jsonArray = JSON.parse(json) as Array<Record<string, Object>>;
      return jsonArray.map(j => converter(j));
    } catch (err) {
      Logger.error('PreferencesJsonStorage', '解析失败', err as Error);
      return [];
    }
  }
}

// ✅ 使用
const storage = new PreferencesJsonStorage();

// 保存对象
await storage.saveObject('current_item', item);

// 读取对象
const item = await storage.getObject('current_item', Item.fromJson);

// 保存数组
await storage.saveArray('recent_items', items);

// 读取数组
const items = await storage.getArray('recent_items', Item.fromJson);

6. 网络请求数据转换

/**
 * API响应模型
 */
export class ApiResponse<T> {
  code: number = 0;
  message: string = '';
  data: T | null = null;
  
  static fromJson<T>(
    json: Record<string, Object>,
    dataConverter: (json: Record<string, Object>) => T
  ): ApiResponse<T> {
    const response = new ApiResponse<T>();
    response.code = json.code as number;
    response.message = json.message as string;
    
    if (json.data) {
      response.data = dataConverter(json.data as Record<string, Object>);
    }
    
    return response;
  }
  
  isSuccess(): boolean {
    return this.code === 200;
  }
}

// ✅ 使用示例
async function fetchItem(id: number): Promise<Item | null> {
  try {
    const responseText = await httpRequest(`/api/items/${id}`);
    const json = JSON.parse(responseText) as Record<string, Object>;
    
    const response = ApiResponse.fromJson(json, Item.fromJson);
    
    if (response.isSuccess()) {
      return response.data;
    } else {
      Logger.error('API', response.message);
      return null;
    }
  } catch (err) {
    Logger.error('API', '请求失败', err as Error);
    return null;
  }
}

关键要点

1. 类型安全

// ✅ 推荐:使用泛型
static parse<T>(json: string): T {
  return JSON.parse(json) as T;
}

// ✅ 推荐:定义fromJson方法
static fromJson(json: Record<string, Object>): Item {
  // 手动映射字段,类型安全
}

// ❌ 避免:直接使用JSON.parse
const obj = JSON.parse(json);  // any类型

2. 字段映射

// ✅ 数据库字段 <-> 对象属性映射
static fromJson(json: Record<string, Object>): Item {
  const item = new Item();
  item.categoryId = json.category_id as number;  // ✅ 映射
  return item;
}

toJson(): Record<string, Object> {
  return {
    category_id: this.categoryId  // ✅ 映射回去
  };
}

3. 错误处理

// ✅ 推荐:try-catch包裹
static safeParse<T>(json: string, defaultValue: T): T {
  try {
    return JSON.parse(json) as T;
  } catch (err) {
    Logger.error('Parse error', err);
    return defaultValue;
  }
}

// ❌ 避免:不处理错误
const obj = JSON.parse(json);  // 可能抛异常

最佳实践

1. 模型类规范

export class Item {
  // 1. 定义属性并初始化
  id: number = 0;
  name: string = '';
  
  // 2. fromJson静态方法
  static fromJson(json: Record<string, Object>): Item {
    const item = new Item();
    item.id = json.id as number;
    item.name = json.name as string;
    return item;
  }
  
  // 3. toJson实例方法
  toJson(): Record<string, Object> {
    return {
      id: this.id,
      name: this.name
    };
  }
}

2. 数组处理

// ✅ 统一的数组转换工具
static parseArray<T>(
  jsonStr: string,
  converter: (json: Record<string, Object>) => T
): T[] {
  try {
    const jsonArray = JSON.parse(jsonStr);
    return jsonArray.map(converter);
  } catch (err) {
    return [];
  }
}

总结

JSON处理要点:

✅ 定义fromJson/toJson方法 ✅ 使用泛型保证类型安全 ✅ try-catch处理解析错误 ✅ 字段名映射(snake_case <-> camelCase) ✅ 嵌套对象递归处理

规范的JSON处理提升代码质量!

在HarmonyOS Next中,处理JSON数据主要使用系统提供的JSON模块。开发者可以使用@ohos.util命名空间下的JSON类进行序列化和反序列化操作。通过JSON.parse()方法可以将JSON字符串转换为对象,而JSON.stringify()方法则可以将对象转换为JSON字符串。此外,ArkTS语言内置了对JSON数据的支持,可以直接操作JSON对象。

在HarmonyOS Next中处理JSON数据,主要有以下几种方式,覆盖你提到的网络请求、本地存储、对象转换和类型安全场景:

1. 网络请求返回JSON

使用@ohos.net.http模块发起HTTP请求,获取JSON字符串响应。

import http from '@ohos.net.http';

let httpRequest = http.createHttp();
httpRequest.request('https://api.example.com/data', {
  method: http.RequestMethod.GET
}, (err, data) => {
  if (!err) {
    let jsonStr = data.result.toString(); // 获取JSON字符串
    // 后续解析...
  }
});

2. JSON解析与序列化

使用内置的JSON对象进行解析和序列化,这是最基础的方法。

// JSON字符串 -> 对象
let jsonString = '{"name": "John", "age": 30}';
let obj = JSON.parse(jsonString);
console.log(obj.name); // "John"

// 对象 -> JSON字符串
let myObj = { name: "Jane", age: 25 };
let str = JSON.stringify(myObj);

3. 类型安全处理(推荐)

对于复杂应用,建议使用ArkTS的类或接口配合JSON.parse()进行类型安全的转换。

// 定义接口
interface User {
  name: string;
  age: number;
  isActive?: boolean; // 可选属性
}

// 解析时指定类型
let jsonString = '{"name": "Alice", "age": 28}';
let user: User = JSON.parse(jsonString) as User; // 类型断言

// 使用对象,编译器会进行类型检查
console.log(user.name.toUpperCase()); // 安全,知道name是string
// console.log(user.age.length); // 编译时报错,age是number

4. 本地数据存储

可以使用@ohos.data.preferences(轻量偏好数据)或@ohos.data.relationalStore(关系型数据库)存储结构化数据。通常先将对象转为JSON字符串再存储。

import preferences from '@ohos.data.preferences';

// 存储
let userPref: preferences.Preferences = await preferences.getPreferences(context, 'myStore');
let userData = { name: "Bob", score: 100 };
await userPref.put('userKey', JSON.stringify(userData));
await userPref.flush();

// 读取
let jsonStr: string = await userPref.get('userKey', '');
let loadedData = JSON.parse(jsonStr);

5. 处理复杂嵌套与日期

对于复杂对象(如包含Date),JSON.parsereviver函数和JSON.stringifyreplacer函数可以自定义处理。

let jsonWithDate = '{"event": "meeting", "time": "2023-10-27T10:00:00.000Z"}';
let objWithDate = JSON.parse(jsonWithDate, (key, value) => {
  if (key === 'time') return new Date(value); // 将特定字符串转为Date对象
  return value;
});
console.log(objWithDate.time.getFullYear()); // 2023

总结要点

  • 基础解析:直接使用全局JSON对象。
  • 类型安全:在ArkTS中定义接口或类,配合类型断言(as)或构造函数,确保数据类型正确。
  • 网络与存储:获取到JSON字符串后,用上述方法解析为对象进行操作;存储前将对象序列化为字符串。
  • 错误处理:解析时使用try-catch处理非法JSON。
try {
  let data = JSON.parse(someString);
} catch (e) {
  console.error('JSON解析失败:', e);
}

HarmonyOS Next的ArkTS基于TypeScript,因此处理JSON时能很好地利用静态类型检查,在开发阶段捕获类型错误,提升代码可靠性。

回到顶部