Javascript

[Typescript] class to json

gilchris 2023. 3. 2. 20:35
Typescript에서 class를 json 문자열로 바꾸는 방법에 대한 고민.
 
일단 평범?하게.. 별 문제없이 성공
class MyTest {
    first = 1;
    second = "It's my test!";
    third: string[] = ["Hello", "World"];
}

console.log(JSON.stringify(new MyTest()));​
 
이렇게 하니까 무한루프를 탄다.
class MyTest {
    first = 1;
    second = "It's my test!";
    third: string[] = ["Hello", "World"];

    toJSON(): string {
        return JSON.stringify(this);
    }
}

const o = new MyTest();
console.log(o.toJSON());
 
이건 또 된다.
class MyTest {
    first = 1;
    second = "It's my test!";
    third: string[] = ["Hello", "World"];

    temp(): void {
        console.log('test');
    }
}

const o = new MyTest();
console.log(JSON.stringify(o));
당연히 temp 함수는 serialize되지 않는다.
 
이것도 된다.
class MyTest {
    first = 1;
    second = "It's my test!";
    third: string[] = ["Hello", "World"];

    toDictionary(): NodeJS.Dict<any> {
        return {
            'first': this.first,
            'second': this.second,
            'third': this.third
        };
    }

    toJSON(): string {
        return JSON.stringify(this.toDictionary());
    }
}

const o = new MyTest();
console.log(o.toJSON());
NodeJS.Dict type은 @types/node 패키지에 있다.

 

toDictionary()를 자동화, 일반화 할 수 없을까? 해서 고민해봤는데..
Object.assign 으로 성공했다!!
class MyTest {
    first = 1;
    second = "It's my test!";
    third: string[] = ["Hello", "World"];

    toDictionary(): NodeJS.Dict<any> {
        return Object.assign({}, this);
    }

    toJSON(): string {
        return JSON.stringify(this.toDictionary());
    }
}

const o = new MyTest();
console.log(o.toJSON());

 

상속으로 일반화 해보자.
class BaseTest {
    toDictionary(): NodeJS.Dict<any> {
        return Object.assign({}, this);
    }

    toJSON(): string {
        return JSON.stringify(this.toDictionary());
    }
}

class MyTest extends BaseTest {
    first = 1;
    second = "It's my test!";
    third: string[] = ["Hello", "World"];
}

const o = new MyTest();
console.log(o.toJSON());
 
Mixins로 해보자.
type Constructor<T = object> = new (...args: any[]) => T; // class를 나타내는 타입. '생성자가 있는 함수'가 곧 클래스.

function SerializableObject<TBase extends Constructor>(Base: TBase) {
    return class extends Base {
        toDictionary(): NodeJS.Dict<any> {
            return Object.assign({}, this);
        }
    
        toJSON(): string {
            return JSON.stringify(this.toDictionary());
        }
    }
}

const MyTest = SerializableObject(class {
    first = 1;
    second = "It's my test!";
    third: string[] = ["Hello", "World"];
});

const o = new MyTest();
console.log(o.toJSON());
링크에 있는 예제와 거의 비슷하다.