Node.js 如何在环回4中设置除持久模型之外的单独DTO

Node.js 如何在环回4中设置除持久模型之外的单独DTO,node.js,loopbackjs,dto,Node.js,Loopbackjs,Dto,考虑一下这个lb4模型 @model({ name: 'users' }) export class User extends Entity { @property({ type: 'number', id: true, }) id: number; @property({ type: 'string', required: true, }) first_name: string; @property({ type: '

考虑一下这个lb4模型

@model({
  name: 'users'
})
export class User extends Entity {
  @property({
    type: 'number',
    id: true,
  })
  id: number;

  @property({
    type: 'string',
    required: true,
  })
  first_name: string;

  @property({
    type: 'string',
  })
  middle_name?: string;

  @property({
    type: 'string',
  })
  last_name?: string;

  @property({
    type: 'string',
    required: true,
  })
  username: string;

  @property({
    type: 'string',
  })
  email?: string;

  @property({
    type: 'string',
  })
  phone?: string;

  @property({
    type: 'string',
    required: true,
  })
  password: string;

  @property({
    type: 'string',
  })
  external_id: string;

  @belongsTo(() => UserTenant)
  created_by: number;

  @belongsTo(() => UserTenant)
  modified_by: number;

  constructor(data?: Partial<User>) {
    super(data);
  }
}
@模型({
名称:'用户'
})
导出类用户扩展实体{
@财产({
键入:“编号”,
id:是的,
})
id:编号;
@财产({
键入:“字符串”,
要求:正确,
})
第一个名称:字符串;
@财产({
键入:“字符串”,
})
中间名?:字符串;
@财产({
键入:“字符串”,
})
姓氏?:字符串;
@财产({
键入:“字符串”,
要求:正确,
})
用户名:字符串;
@财产({
键入:“字符串”,
})
电子邮件?:字符串;
@财产({
键入:“字符串”,
})
电话?:字符串;
@财产({
键入:“字符串”,
要求:正确,
})
密码:字符串;
@财产({
键入:“字符串”,
})
外部_id:字符串;
@belongsTo(()=>UserTenant)
创建人:编号;
@belongsTo(()=>UserTenant)
修改人:编号;
构造函数(数据?:部分){
超级(数据);
}
}

当前,如果我们使用lb4 cli为此模型创建存储库和控制器,它将使用与输入/输出相同的模型生成路由方法CRUD。然而,我们想要的是有一个单独的DTO模型(非持久化到DB)用作控制器的输入/输出DTO,不包括属性密码、创建者和修改者。一种方法是手动创建这样一个模型类,并编写一个转换器类,该类将UserDTO对象转换为上面的用户模型(复制单个属性)。但这似乎是一项开销。此外,我们希望对更多的模型进行此操作。所以,以这种方式做似乎不是正确的方法。lb4是否提供了更好的方法来实现这一点?

显然,目前有一种方法可以在lb4中本地“隐藏”属性。然后,我用一个新的实体HideableEntity(扩展实体)修改了实体类。在HideableEntity中,我修改了toJson()函数,如下所示:

import {Entity, AnyObject} from '@loopback/repository';
import {Options} from '@loopback/repository/src/common-types';

export abstract class HideableEntity extends Entity {
  /**
   * Serialize into a plain JSON object
   */
  toJSON(): Object {
    const def = (<typeof HideableEntity>this.constructor).definition;
    if (def == null || def.settings.strict === false) {
      return this.toObject({ignoreUnknownProperties: false});
    }

    const json: AnyObject = {};
    for (const p in def.properties) {
      if (p in this) {
        json[p] = asJSON((this as AnyObject)[p]);
      }
    }
    return json;
  }

  /**
   * Convert to a plain object as DTO
   */
  toObject(options?: Options): Object {
    const def = (<typeof HideableEntity>this.constructor).definition;

    let obj: AnyObject;
    if (options && options.ignoreUnknownProperties === false) {
      obj = {};
      for (const p in this) {
        if (def != null && def.properties[p] && def.properties[p]['hide']) {
          continue;
        }
        let val = (this as AnyObject)[p];
        obj[p] = asObject(val, options);
      }
    } else {
      obj = this.toJSON();
    }
    return obj;
  }
}

function asJSON(value: any): any {
  if (value == null) return value;
  if (typeof value.toJSON === 'function') {
    return value.toJSON();
  }
  // Handle arrays
  if (Array.isArray(value)) {
    return value.map(item => asJSON(item));
  }
  return value;
}

function asObject(value: any, options?: Options): any {
  if (value == null) return value;
  if (typeof value.toObject === 'function') {
    return value.toObject(options);
  }
  if (typeof value.toJSON === 'function') {
    return value.toJSON();
  }
  if (Array.isArray(value)) {
    return value.map(item => asObject(item, options));
  }
  return value;
}
在上述情况下,密码将被隐藏

export class User extends HideableEntity {
  @property({
    type: 'number',
    id: true,
    required: false,
  })
  id: number;

    @property({
        type: 'string',
        required: true,
    })
    email: string;

    @property({
        type: 'string',
        required: true,
        hide: true,
    })
    password: string;

    [...]