Я не могу сериализовать вложенный набор классов в json:
import { readFileSync } from 'fs'
class Address {
constructor(
public readonly street: string,
public readonly city: string){}
}
class Person {
constructor(
public readonly address: Address,
public readonly name: string){}
}
class School {
private students = new Map<string, Person>();
public add(student: Person): School {
this.students.set(student.name, student);
return this;
}
public toJson(filename: string) {
}
}
const p1 = new Person(new Address("5th Ave.", "NYC"), "moish");
const p2 = new Person(new Address("remi", "Boston"), "dave");
const p3 = new Person(new Address("Dart", "Boston"), "uzi");
let school = new School();
school.add(p1).add(p2).add(p3)
console.info(school); // <--- good ! but wrong format 🤓🤓🤓
console.info(JSON.stringify(school)); // doesn't work: {"students":{}} 🥶🥶🥶
И вот как я его компилирую и запускаю:
% npx tsc --target es2022 --moduleResolution node main.ts
% node main.js
School {
students: Map(3) {
'moish' => Person { address: [Address], name: 'moish' },
'dave' => Person { address: [Address], name: 'dave' },
'uzi' => Person { address: [Address], name: 'uzi' }
}
}
{"students":{}}
Нет встроенной поддержки сериализации Map
в JSON. Но вы можете переопределить метод toJSON
.
class School {
students = new Map();
add(student) {
this.students.set(student.name, student)
return this;
}
toJSON() {
return {
students: Object.fromEntries(this.students)
}
}
}
class Student {
constructor(name) {
this.name = name
}
}
const school = new School().add(new Student('A')).add(new Student('B')).add(new Student('C'))
console.info(JSON.stringify(school))
Правильное имя метода для настройки значения, используемого во время сериализации JSON объекта, — toJSON().
В вашем случае вам просто нужно предоставить сериализуемый тип данных вместо Map , например, объект. Вы можете использовать метод Object.fromEntries() в методе итератора entry() для создания такого объекта:
toJSON (): { students: Record<string, Person> } {
return { students: Object.fromEntries(this.students.entries()) };
}
Вот полный пример, основанный на коде, который вы показали в своем вопросе:
class Address {
constructor (
public readonly street: string,
public readonly city: string,
) {}
}
class Person {
constructor (
public readonly address: Address,
public readonly name: string,
) {}
}
class School {
private students = new Map<string, Person>();
public add (student: Person): School {
this.students.set(student.name, student);
return this;
}
public toJSON (): { students: Record<string, Person> } {
return { students: Object.fromEntries(this.students.entries()) };
}
}
console.clear();
const p1 = new Person(new Address("5th Ave.", "NYC"), "moish");
const p2 = new Person(new Address("remi", "Boston"), "dave");
const p3 = new Person(new Address("Dart", "Boston"), "uzi");
const school = new School();
school.add(p1).add(p2).add(p3);
console.info(JSON.stringify(school)); // {"students":{"moish":{"address":{"street":"5th Ave.","city":"NYC"},"name":"moish"},"dave":{"address":{"street":"remi","city":"Boston"},"name":"dave"},"uzi":{"address":{"street":"Dart","city":"Boston"},"name":"uzi"}}}
Скомпилированный JS из TS Playground:
"use strict";
class Address {
constructor(street, city) {
this.street = street;
this.city = city;
}
}
class Person {
constructor(address, name) {
this.address = address;
this.name = name;
}
}
class School {
constructor() {
this.students = new Map();
}
add(student) {
this.students.set(student.name, student);
return this;
}
toJSON() {
return { students: Object.fromEntries(this.students.entries()) };
}
}
console.clear();
const p1 = new Person(new Address("5th Ave.", "NYC"), "moish");
const p2 = new Person(new Address("remi", "Boston"), "dave");
const p3 = new Person(new Address("Dart", "Boston"), "uzi");
const school = new School();
school.add(p1).add(p2).add(p3);
console.info(JSON.stringify(school)); // {"students":{"moish":{"address":{"street":"5th Ave.","city":"NYC"},"name":"moish"},"dave":{"address":{"street":"remi","city":"Boston"},"name":"dave"},"uzi":{"address":{"street":"Dart","city":"Boston"},"name":"uzi"}}}
Ссылка на тип утилиты Record<Keys, Type>
: https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type
students
, который представляет собой объект со строковыми ключами и Person
значениями.
можете ли вы объяснить возвращаемый тип
toJSON
? я не уверен, что понимаю это