이것들은 몇 가지 다른 방법을 보여주기 위해 이것에 대한 빠른 샷입니다. 그것들은 결코 "완전한"것이 아니며, 면책 조항으로, 이렇게하는 것이 좋은 생각이라고 생각하지 않습니다. 또한 코드를 함께 빨리 입력했기 때문에 코드가 너무 깨끗하지 않습니다.
또한 참고 : 물론 역 직렬화 가능 클래스에는 모든 종류의 역 직렬화를 알고있는 다른 모든 언어의 경우와 마찬가지로 기본 생성자가 있어야합니다. 물론, 인수없이 기본이 아닌 생성자를 호출해도 Javascript는 불만을 제기하지 않지만 클래스를 준비하는 것이 좋습니다.
옵션 # 1 : 런타임 정보가 전혀 없음
이 방법의 문제점은 대부분 멤버의 이름이 해당 클래스와 일치해야한다는 것입니다. 클래스별로 같은 유형의 멤버로 자동 제한하고 여러 가지 모범 사례 규칙을 위반합니다. 나는 이것에 대해 강력히 권고하지만,이 답변을 썼을 때 처음으로 "초안"이었기 때문에 여기에 적어 두십시오.
module Environment {
export class Sub {
id: number;
}
export class Foo {
baz: number;
Sub: Sub;
}
}
function deserialize(json, environment, clazz) {
var instance = new clazz();
for(var prop in json) {
if(!json.hasOwnProperty(prop)) {
continue;
}
if(typeof json[prop] === 'object') {
instance[prop] = deserialize(json[prop], environment, environment[prop]);
} else {
instance[prop] = json[prop];
}
}
return instance;
}
var json = {
baz: 42,
Sub: {
id: 1337
}
};
var instance = deserialize(json, Environment, Environment.Foo);
console.log(instance);
옵션 # 2 : 이름 속성
옵션 # 1의 문제를 해결하려면 JSON 객체의 노드 유형에 대한 정보가 필요합니다. 문제는 Typescript에서 이러한 것들이 컴파일 타임 구조이며 런타임에 필요하다는 것입니다. 그러나 런타임 객체는 속성이 설정 될 때까지 속성을 인식하지 못합니다.
이를 수행하는 한 가지 방법은 클래스에 이름을 알리는 것입니다. 하지만 JSON에서도이 속성이 필요합니다. 실제로, 당신 은 json 에서만 필요합니다 :
module Environment {
export class Member {
private __name__ = "Member";
id: number;
}
export class ExampleClass {
private __name__ = "ExampleClass";
mainId: number;
firstMember: Member;
secondMember: Member;
}
}
function deserialize(json, environment) {
var instance = new environment[json.__name__]();
for(var prop in json) {
if(!json.hasOwnProperty(prop)) {
continue;
}
if(typeof json[prop] === 'object') {
instance[prop] = deserialize(json[prop], environment);
} else {
instance[prop] = json[prop];
}
}
return instance;
}
var json = {
__name__: "ExampleClass",
mainId: 42,
firstMember: {
__name__: "Member",
id: 1337
},
secondMember: {
__name__: "Member",
id: -1
}
};
var instance = deserialize(json, Environment);
console.log(instance);
옵션 # 3 : 명시 적으로 멤버 유형을 명시
위에서 언급했듯이 클래스 멤버의 유형 정보는 런타임에 사용할 수 없습니다. 즉, 사용 가능하지 않은 경우입니다. 우리는 기본이 아닌 멤버에게만이 작업을 수행하면되며 다음과 같이 진행하면됩니다.
interface Deserializable {
getTypes(): Object;
}
class Member implements Deserializable {
id: number;
getTypes() {
// since the only member, id, is primitive, we don't need to
// return anything here
return {};
}
}
class ExampleClass implements Deserializable {
mainId: number;
firstMember: Member;
secondMember: Member;
getTypes() {
return {
// this is the duplication so that we have
// run-time type information :/
firstMember: Member,
secondMember: Member
};
}
}
function deserialize(json, clazz) {
var instance = new clazz(),
types = instance.getTypes();
for(var prop in json) {
if(!json.hasOwnProperty(prop)) {
continue;
}
if(typeof json[prop] === 'object') {
instance[prop] = deserialize(json[prop], types[prop]);
} else {
instance[prop] = json[prop];
}
}
return instance;
}
var json = {
mainId: 42,
firstMember: {
id: 1337
},
secondMember: {
id: -1
}
};
var instance = deserialize(json, ExampleClass);
console.log(instance);
옵션 # 4 : 장황하지만 깔끔한 방법
2016 년 1 월 3 일 업데이트 : @GameAlchemist 가 Typescript 1.7 의 의견 ( idea , implementation ) 에서 지적했듯이 아래 설명 된 솔루션은 클래스 / 속성 데코레이터를 사용하여 더 나은 방법으로 작성할 수 있습니다.
직렬화는 항상 문제이며 제 생각에 가장 좋은 방법은 가장 짧지 않은 방법입니다. 모든 옵션 중에서 클래스의 작성자가 deserialized 객체의 상태를 완전히 제어 할 수 있기 때문에 이것이 내가 선호하는 것입니다. 내가 추측해야한다면, 다른 모든 옵션이 조만간 당신을 곤경에 빠뜨릴 것이라고 말하고 싶습니다 (Javascript가 이것을 다루는 기본 방법을 제시하지 않는 한).
실제로 다음 예제는 유연성 정의를 수행하지 않습니다. 실제로 클래스의 구조를 복사합니다. 그러나 여기서 명심해야 할 차이점은 클래스가 전체 클래스의 상태를 제어하려는 모든 종류의 JSON을 사용하도록 모든 권한을 가지고 있다는 것입니다 (사물 등을 계산할 수 있음).
interface Serializable<T> {
deserialize(input: Object): T;
}
class Member implements Serializable<Member> {
id: number;
deserialize(input) {
this.id = input.id;
return this;
}
}
class ExampleClass implements Serializable<ExampleClass> {
mainId: number;
firstMember: Member;
secondMember: Member;
deserialize(input) {
this.mainId = input.mainId;
this.firstMember = new Member().deserialize(input.firstMember);
this.secondMember = new Member().deserialize(input.secondMember);
return this;
}
}
var json = {
mainId: 42,
firstMember: {
id: 1337
},
secondMember: {
id: -1
}
};
var instance = new ExampleClass().deserialize(json);
console.log(instance);