HarmonyOS鸿蒙Next中interface实例怎么仅解析自己定义的字段?

HarmonyOS鸿蒙Next中interface实例怎么仅解析自己定义的字段? 鸿蒙next 使用 interface 实例的对象在数据解析的时候会把接口上其他键值也复制过来 比如我在页面定义

@State
detail: CircleDo = {} as CircleDo

请求后

this.detail = res.data.detail

this.detail会拿到json上有但是interface上并没有定义的键值 解析方法如下:

let jsonObject: object = JSON.parse(res.result.toString()) as object
const result = jsonObject as ResponseData<T>

如果我定义一个类继承该接口

export class CirlceModel implements CircleDo
const model:CirlceModel = new CirlceModel(res.data.detail)
this.detail=model

这样detail就是我自定义的字段内容了,有什么方法可以让interface的实例仅解析定义的字段?


更多关于HarmonyOS鸿蒙Next中interface实例怎么仅解析自己定义的字段?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

【解决方案】

在ArkTS中,由于interface是纯编译时类型,运行时不存在对应的类型信息,因此无法直接通过类型系统自动过滤多余字段。但可以通过一些技巧让保留字段列表与接口定义自动关联(避免手动拼写字段的麻烦),从而间接实现非手动指定的效果。

方案一:手动指定保留字段列表。

要让实例仅保留接口中定义的字段,可以在运行时手动过滤多余的属性。核心思路是:明确接口中定义的字段列表,然后从后端数据中提取这些字段,组成新对象。

// 在ts文件中声明interface和过滤函数
// 1.定义接口(仅包含需要的字段)
export interface User {
  name: string;
  age: number;
  sex: string;
}

// 2.过滤函数:仅保留接口中定义的字段
export function pickDefinedFields<T>(data: any, allowedFields: Array<keyof T>): T {
  const result: Partial<T> = {};
  allowedFields.forEach(field => {
    // 从原始数据中提取字段(如果存在)
    if (data.hasOwnProperty(field)) {
      result[field] = data[field];
    }
  });
  return result as T;
}

在ArkTS文件中调用:

// 3.声明需要保留的字段列表(与接口字段一一对应)
const ALLOWED_FIELDS: Array<keyof User> = ['name', 'age', 'sex'];

let jsonStr: string = '{"name": "xx","age": 30,"sex": "男","addr": "xxx-xxx-xxx","phone": "1xxxxxxxxxx"}';
let user: User = {} as User;
user = JSON.parse(jsonStr);
// 4.使用过滤函数处理后赋值,确保仅保留接口字段
user = pickDefinedFields<User>(JSON.parse(jsonStr), ALLOWED_FIELDS);
// {
//   "name":"xx",
//   "age":30,
//   "sex":"男",
// }

方案二:利用“字段映射对象”关联类型与运行时字段。

通过一个字段映射对象(仅用于类型关联,无需实际值),同时生成接口类型和运行时的字段列表,确保两者完全同步。

// 在ts文件中声明interface和过滤函数
// 1.定义一个“字段映射对象”(值无关,仅用键名)
const userFields = {
  name: '',
  age: 0,
  sex: ''
} as const;

// 2.从映射对象中自动推导接口类型(与映射对象的键完全一致)
export type User = {
  [K in keyof typeof userFields]: typeof userFields[K] extends string ? string :
    typeof userFields[K] extends number ? number : any;
};

// 3.从映射对象中自动提取运行时字段列表
export const allowedFields = Object.keys(userFields) as Array<keyof User>;

// 4.通用过滤函数(与之前相同)
export function pick<T>(data: any, fields: Array<keyof T>): T {
  const result: Partial<T> = {};
  fields.forEach(field => {
    if (data.hasOwnProperty(field)) {
      result[field] = data[field];
    }
  });
  return result as T;
}

在ArkTS文件中调用:

let jsonStr: string = '{"name": "xx","age": 30,"sex": "男","addr": "xxx-xxx-xxx","phone": "1xxxxxxxxxx"}';
let user: User = pick(JSON.parse(jsonStr), allowedFields);
// {
//   "name":"xx",
//   "age":30,
//   "sex":"男",
// }

该方案的优点是字段列表(allowedFields)与接口(User)通过userFields自动关联,修改userFields时,类型和运行时字段会同步更新,避免手动维护的错误。

更多关于HarmonyOS鸿蒙Next中interface实例怎么仅解析自己定义的字段?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


可以使用class-transformer三方库,同时需要安装reflect-metadata。

使用方法:

class CirlceModel { id: number = 0 name: string = ‘’ }

import * as ClassTransformerUtil from ‘class-transformer’

import ‘reflect-metadata’

const cirlceModel = ClassTransformerUtil.plainToClass(CirlceModel, res.data.detail)

用class直接就可以解析了,我需要interface的,

在HarmonyOS Next中,可通过@SerializedName注解标记自定义字段,并使用JsonReaderskipValue()方法跳过未定义字段。示例代码:

import serializer from '@ohos.serializer';

class CustomInterface {
  @SerializedName('myField')
  myField: string = '';
}

let jsonStr = '{"myField":"value", "unknownField":"skipThis"}';
let custom = serializer.fromJson(jsonStr, CustomInterface);

这样仅解析myField,忽略unknownField。需在build-profile.json5中启用enableSerializer: true

在HarmonyOS Next中,interface在TypeScript/ArkTS中仅作为类型约束,运行时不会过滤未定义字段。要实现仅解析定义字段,推荐以下方案:

  1. 使用类替代interface,在构造函数中显式赋值:
export class CircleDo {
  // 定义需要的字段
  id: number = 0;
  name: string = '';
  
  constructor(data?: any) {
    if (data) {
      this.id = data.id || 0;
      this.name = data.name || '';
    }
  }
}
  1. 使用对象解构:
this.detail = {
  id: res.data.detail.id,
  name: res.data.detail.name
} as CircleDo;
  1. 使用工具函数过滤:
function filterFields<T>(source: any, template: T): T {
  const result = {} as T;
  Object.keys(template).forEach(key => {
    if (source.hasOwnProperty(key)) {
      result[key] = source[key];
    }
  });
  return result;
}

this.detail = filterFields(res.data.detail, {} as CircleDo);

类方案最推荐,它提供了明确的类型安全和字段控制,符合HarmonyOS Next的最佳实践。

回到顶部