JSON para instância de classe TypeScript?




deserialization (4)

Esta pergunta já tem uma resposta aqui:

Eu fiz algumas pesquisas, mas não estou totalmente satisfeito com o que encontrei. Só para ter certeza, aqui está minha pergunta: Qual é realmente a solução automatizada mais robusta e elegante para desserializar as instâncias de classe de tempo de execução JSON para TypeScript?

Digamos que recebi esta aula:

class Foo {
  name: string;
  GetName(): string { return this.name };
}

E digamos que eu peguei essa string JSON para desserialização:

{"name": "John Doe"}

Qual é a solução melhor e mais sustentável de obter uma instância de uma classe Foo com o nome definido como "John Doe" e o método GetName () para funcionar? Estou perguntando muito especificamente porque sei que é fácil desserializar para um objeto de dados puro. Gostaria de saber se é possível obter uma instância de classe com métodos de trabalho, sem ter que fazer nenhuma análise manual ou copiar dados manualmente. Se uma solução totalmente automatizada não for possível, qual é a próxima melhor solução?


Answer #1

Agora você pode usar Object.assign(target, ...sources) . Seguindo o seu exemplo, você pode usá-lo assim:

class Foo {
  name: string;
  getName(): string { return this.name };
}

let fooJson: string = '{"name": "John Doe"}';
let foo: Foo = Object.assign(new Foo(), JSON.parse(fooJson));

console.log(foo.getName()); //returns John Doe

Object.assign faz parte do ECMAScript 2015 e está atualmente disponível na maioria dos navegadores modernos.


Answer #2

Qual é realmente a solução automatizada mais robusta e elegante para desserializar instâncias de classe de tempo de execução JSON para TypeScript?

O uso de decoradores de propriedades com o ReflectDecorators para registrar informações do tipo acessível em tempo de execução que podem ser usadas durante um processo de desserialização fornece uma abordagem surpreendentemente limpa e amplamente adaptável, que também se encaixa perfeitamente no código existente. Também é totalmente automatizável e funciona também para objetos aninhados.

Uma implementação dessa idéia é TypedJSON , que eu criei precisamente para esta tarefa:

@JsonObject
class Foo {
    @JsonMember
    name: string;

    getName(): string { return this.name };
}
var foo = TypedJSON.parse('{"name": "John Doe"}', Foo);

foo instanceof Foo; // true
foo.getName(); // "John Doe"

Answer #3

Por que você não pode simplesmente fazer algo assim?

class Foo {
  constructor(myObj){
     Object.assign(this, myObj);
  }
  get name() { return this._name; }
  set name(v) { this._name = v; }
}

let foo = new Foo({ name: "bat" });
foo.toJSON() //=> your json ...

Answer #4

A melhor solução que encontrei ao lidar com classes Typescript e objetos json: adicione um construtor em sua classe Typescript que tome os dados json como parâmetro. Nesse construtor, você estende seu objeto json com jQuery, assim: $ .extend (this, jsonData). $ .extend permite manter os protótipos javascript enquanto adiciona as propriedades do objeto json.

export class Foo
{
    Name: string;
    getName(): string { return this.Name };

    constructor( jsonFoo: any )
    {
        $.extend( this, jsonFoo);
    }
}

Em seu retorno de chamada ajax, traduza seus jsons em um objeto de texto datilografado como este:

onNewFoo( jsonFoos : any[] )
{
  let receviedFoos = $.map( jsonFoos, (json) => { return new Foo( json ); } );

  // then call a method:
  let firstFooName = receviedFoos[0].GetName();
}

Se você não adicionar o construtor, chame juste no seu retorno de chamada ajax:

let newFoo = new Foo();
$.extend( newFoo, jsonData);
let name = newFoo.GetName()

... mas o construtor será útil se você quiser converter também o objeto json filho. Veja minha resposta detalhada here .





deserialization