MikroORM中@ManyToOne关联Ref序列化格式问题求助
问题
使用带有@ManyToOne关联Ref类型的实体序列化JSON时,city字段仅返回ID字符串(如"city": "bd612c71"),但预期返回包含id的对象格式(如{"city": {"id": "bd612c71"}})。
当前返回JSON示例
{"id": "80856ca0","createdAt": "2023-07-10T01:48:48.000Z","updatedAt": "2023-07-10T01:48:48.000Z","hospital": {"id": "d8f6f9ce","city": "bd612c71","country": {"id": "cfb0a1c6","createdAt": "2023-07-10T01:48:48.000Z","updatedAt": "2023-07-10T01:48:48.000Z"},"deletedAt": null}}
相关实体代码
Hospital实体
@Entity({tableName: 'hospital'}) export default class Hospital extends AggregateRoot<Hospital, 'id'> { @PrimaryKey({ autoincrement: false, unique: true, type: 'varchar', length: 8, nullable: false }) id!: string @ManyToOne(() => City, { ref: true }) city!: Ref<City> @ManyToOne(() => Country, { ref: true }) country!: Ref<Country> // More properties here }
City实体
@Entity({tableName: 'city'}) export default class City extends AggregateRoot<City, 'id'> { @PrimaryKey({ autoincrement: false, unique: true, type: 'varchar', length: 8, nullable: false }) id!: string @Property({ unique: true, type: 'character', length: 100, nullable: false }) name!: string @OneToMany(() => Hospital, hospital => hospital.city) hospitals = new Collection<Hospital>(this) }
注:
AggregateRoot为自定义类,继承自BaseEntity<T, PK>
解决方案
这不是Bug,是Ref类型序列化的默认行为——Ref本身仅存储关联实体的ID,序列化时会直接输出ID字符串。要实现预期的对象格式,可通过以下几种方式处理:
1. 自定义实体的toJSON方法
在Hospital类中重写toJSON方法,手动将city转换为包含id的对象:
@Entity({tableName: 'hospital'}) export default class Hospital extends AggregateRoot<Hospital, 'id'> { // ... 原有属性定义 toJSON() { const json = super.toJSON(); if (this.city) { json.city = { id: this.city.id }; } return json; } }
如果country也需要统一格式,可同理处理。
2. 使用DTO(数据传输对象)转换
创建专门的HospitalDTO类,在序列化前将实体转换为DTO格式:
class HospitalDTO { id: string; createdAt: Date; updatedAt: Date; city: { id: string }; country: { id: string; createdAt: Date; updatedAt: Date }; // 其他需要的字段 static fromEntity(hospital: Hospital): HospitalDTO { return { id: hospital.id, createdAt: hospital.createdAt, updatedAt: hospital.updatedAt, city: { id: hospital.city.id }, country: { id: hospital.country.id, createdAt: hospital.country.createdAt, updatedAt: hospital.country.updatedAt } // 映射其他字段 }; } } // 使用时 const hospital = await hospitalRepository.findOne(...); const hospitalDTO = HospitalDTO.fromEntity(hospital); const json = JSON.stringify(hospitalDTO);
3. 调整关联配置(需权衡场景)
若不想用Ref类型,可移除{ ref: true }配置,直接关联City实体,但这样会导致查询时默认加载关联实体(可通过lazy: true配置懒加载),会增加数据库查询开销,需根据业务场景权衡:
@ManyToOne(() => City) // 移除ref: true city!: City;
此时序列化时会输出实体对象(仅加载的字段),但如果是懒加载且未主动加载,可能会出现序列化异常。
内容的提问来源于stack exchange,提问作者z0mbieKale
相关产品推荐
相关产品推荐

