programing

타이프스크립트 오브젝트 시리얼화?

mbctv 2023. 3. 22. 22:00
반응형

타이프스크립트 오브젝트 시리얼화?

타입스크립트 오브젝트가 타입 정보를 잃지 않도록 JSON의 시리얼화/디시리얼화 방법이 있습니까?간단하죠.JSON.parse(JSON.stringify)에 주의사항이 너무 많습니다.

아니면 애드혹 솔루션을 사용해야 하나요?

인터페이스를 사용하여 강력한 유형 가져오기:

// Creating 
var foo:any = {};
foo.x = 3;
foo.y='123';

var jsonString = JSON.stringify(foo);
alert(jsonString);


// Reading
interface Bar{
    x:number;
    y?:string; 
}

var baz:Bar = JSON.parse(jsonString);
alert(baz.y);

필요에 따라서, 타입 어설션 「<>」를 사용합니다.

Object.assign(단, ECMAScript 2015가 필요)을 사용하는 것이 이 문제를 해결하는 더 나은 방법이라고 생각합니다.

소정의 클래스

class Pet {
    name: string;
    age: number;
    constructor(name?: string, age?: number) {
        this.name = name;
        this.age = age;
    }
    getDescription(): string {
        return "My pet " + this.name + " is " + this.age + " years old.";
    }
    static fromJSON(d: Object): Pet {
        return Object.assign(new Pet(), d);
    }
}

이렇게 직렬화 및 직렬화 해제...

var p0 = new Pet("Fido", 5);
var s = JSON.stringify(p0);
var p1 = Pet.fromJSON(JSON.parse(s));
console.log(p1.getDescription());

이 예를 다음 단계로 진행하려면 중첩된 개체를 고려하십시오.

class Type {
    kind: string;
    breed: string;
    constructor(kind?: string, breed?: string) {
        this.kind = kind;
        this.breed = breed;
    }
    static fromJSON(d: Object) {
        return Object.assign(new Type(), d);
    }
}
class Pet {
    name: string;
    age: number;
    type: Type;
    constructor(name?: string, age?: number) {
        this.name = name;
        this.age = age;
    }
    getDescription(): string {
        return "My pet " + this.name + " is " + this.age + " years old.";
    }
    getFullDescription(): string {
        return "My " + this.type.kind + ", a " + this.type.breed + ", is " + this.age + " years old.";
    }
    static fromJSON(d: Object): Pet {
        var o = Object.assign(new Pet(), d);
        o.type = Type.fromJSON(o['type']);
        return o;
    }
}

이렇게 직렬화 및 직렬화 해제...

var q0 = new Pet("Fido", 5);
q0.type = new Type("dog", "Pomeranian");
var t = JSON.stringify(q0);
var q1 = Pet.fromJSON(JSON.parse(t));
console.log(q1.getFullDescription());

따라서 인터페이스를 사용하는 것과 달리 이 접근법은 메서드를 유지합니다.

지금까지 발견된 가장 좋은 방법은 "jackson-js"를 사용하는 것입니다.jackson-js는 ts-decorator를 사용하여 클래스를 기술한 후 유형 정보 저장을 직렬화하고 원하는 프로젝트입니다.어레이, 맵 등을 지원합니다.

풀 튜토리얼 : https://itnext.io/jackson-js-powerful-javascript-decorators-to-serialize-deserialize-objects-into-json-and-vice-df952454cf

간단한 예:

import { JsonProperty, JsonClassType, JsonAlias, ObjectMapper } from 'jackson-js';

class Book {
  @JsonProperty() @JsonClassType({type: () => [String]})
  name: string;
  @JsonProperty() @JsonClassType({type: () => [String]})
  @JsonAlias({values: ['bkcat', 'mybkcat']})
  category: string;
}

class Writer {
  @JsonProperty() @JsonClassType({type: () => [Number]})
  id: number;
  @JsonProperty() @JsonClassType({type: () => [String]})
  name: string;
  @JsonProperty() @JsonClassType({type: () => [Array, [Book]]})
  books: Book[] = [];
}

const objectMapper = new ObjectMapper();
// eslint-disable-next-line max-len
const jsonData = '{"id":1,"name":"John","books":[{"name":"Learning TypeScript","bkcat":"Web Development"},{"name":"Learning Spring","mybkcat":"Java"}]}';
const writer = objectMapper.parse<Writer>(jsonData, {mainCreator: () => [Writer]});
console.log(writer);
/*
Writer {
  books: [
    Book { name: 'Learning TypeScript', category: 'Web Development' },
    Book { name: 'Learning Spring', category: 'Java' }
  ],
  id: 1,
  name: 'John'
}
*/

같은 일을 한다고 주장하는 다른 프로젝트도 몇 가지 있습니다.

그러나 TypeScript Map을 사용했을 때 유일하게 Jackson-js가 작동했습니다.

ts-jackson을 사용하는 것도 추천합니다.

이것은 타이프스크립트를 염두에 두고 작성되었으며 깊이 중첩된 구조를 해결할 수 있습니다.

나는 AQuirky의 대답이 통한다.Object.assign 메서드에 문제가 있을 수 있습니다.tsconfig.json을 다음과 같이 수정해야 했습니다.

"compilerOptions": {
    ...
    "lib": ["es2015"],
    ...
}

먼저 API에서 JSON으로 수신한 소스 엔티티의 인터페이스를 작성해야 합니다.

interface UserEntity {
  name: string,
  age: number,
  country_code: string
};

둘째, 컨스트럭터를 사용하여 모델을 구현합니다.여기서 몇 가지 필드 이름을 커스터마이즈(카멜라이즈)할 수 있습니다.

  class User  {
    constructor({ name, age, country_code: countryCode }: UserEntity) {
      Object.assign(this, { name, age, countryCode });
    }
  }

마지막으로 JavaScript 객체 "jsonUser"를 사용하여 사용자 모델의 인스턴스를 만듭니다.

    const jsonUser = {name: 'Ted', age: 2, country_code: 'US'};

    const userInstance = new User(jsonUser);

    console.log({ userInstance })

결과 로그

여기 놀이터 링크가 있습니다.

AQuirky의 답변은 좋은 출발점이지만, 제 코멘트에서 언급했듯이, AQuirky의 주요 문제는 정의되지 않은 필드를 가진 개체를 만들 수 있어야 한다는 것입니다. 그리고 나서 AQuirky의 답변은 그의 코멘트로 채워집니다.fromJSON★★★★★★ 。

이는 RAII 원칙을 위반하여 불완전한 Pet을 작성하는 함정에 빠질 수 있는 해당 클래스의 사용자를 혼란스럽게 할 수 있습니다(여기에서는 인수를 지정하지 않고 컨스트럭터를 호출한 후 오브젝트를 입력하기 위해 JSON()에서 호출해야 합니다).

이 답변에 기초하여 JavaScript의 프로토타입 체인을 사용하여 직렬화/비직렬화 후 클래스의 개체를 다시 얻을 수 있는 방법이 있습니다.중요한 방법은 직렬화 및 역직렬화 후 올바른 프로토타입 개체를 다시 할당하는 것입니다.

class Foo {}
foo1 = new Foo();
foo2 = JSON.parse(JSON.stringify(p1))
foo2.__proto__ = Foo.prototype;

여기에 이미지 설명을 입력하십시오.

이 방법을 AQuirky의 를 수정하기 AQuirky의 예를 .fromJSON

static fromJSON(d: Object): Pet {
    d.__proto__ = Pet.prototype;
    return p
}

언급URL : https://stackoverflow.com/questions/16261119/typescript-objects-serialization

반응형