Eu li um objeto JSON de um servidor REST remoto. Este objeto JSON possui todas as propriedades de uma classe de texto datilografada (por design). Como converter esse objeto JSON recebido em um tipo var?
Não quero preencher um var datilografado (ou seja, ter um construtor que aceite esse objeto JSON). É grande e copiar tudo através de subobjeto por subobjeto e propriedade por propriedade levaria muito tempo.
Atualização: No entanto, você pode convertê-lo em uma interface de texto datilografado!
json
typescript
David Thielen
fonte
fonte
Respostas:
Você não pode simplesmente converter um resultado JavaScript simples e antigo de uma solicitação Ajax em uma instância de classe JavaScript / TypeScript prototípica. Existem várias técnicas para fazer isso e geralmente envolvem a cópia de dados. A menos que você crie uma instância da classe, ela não terá métodos ou propriedades. Ele permanecerá um objeto JavaScript simples.
Embora se você estivesse lidando apenas com dados, poderia fazer uma conversão para uma interface (por ser puramente uma estrutura de tempo de compilação), isso exigiria o uso de uma classe TypeScript que usa a instância de dados e executa operações com esses dados.
Alguns exemplos de cópia dos dados:
Em essência, você apenas:
fonte
JSON.parse()
. Ambos ainda precisariam ser feitos, mas sintaticamente poderiam ser combinados.Object.setPrototypeOf
Eu tive o mesmo problema e encontrei uma biblioteca que faz o trabalho: https://github.com/pleerock/class-transformer .
Funciona assim:
Ele suporta crianças aninhadas, mas você precisa decorar o membro da sua turma.
fonte
@Type
embora não esqueça suas anotações). Esta resposta merece mais crédito.No TypeScript, você pode fazer uma asserção de tipo usando uma interface e genéricos como:
Onde ILocationMap descreve a forma dos seus dados. A vantagem desse método é que seu JSON pode conter mais propriedades, mas a forma satisfaz as condições da interface.
Espero que ajude!
fonte
Se você estiver usando o ES6, tente o seguinte:
Mas, dessa maneira , não funcionará no objeto ninho , infelizmente.
fonte
Object.create(MyClass.prototype)
, ignorando completamente o construtor.Encontrei um artigo muito interessante sobre a conversão genérica de JSON para uma classe Typescript:
http://cloudmark.github.io/Json-Mapping/
Você acaba com o seguinte código:
fonte
TLDR: um revestimento
A resposta detalhada
Eu não recomendaria a abordagem Object.assign, pois ela pode sobrecarregar inadequadamente sua instância de classe com propriedades irrelevantes (bem como fechamentos definidos) que não foram declarados na própria classe.
Na classe em que você está tentando desserializar, eu garantiria que todas as propriedades que você deseja desserializar sejam definidas (nulo, matriz vazia, etc.). Ao definir suas propriedades com valores iniciais, você expõe sua visibilidade ao tentar iterar os membros da classe para os quais atribuir valores (consulte desserializar o método abaixo).
No exemplo acima, eu simplesmente criei um método de desserialização. Em um exemplo do mundo real, eu o centralizaria em uma classe base ou método de serviço reutilizável.
Aqui está como utilizar isso em algo como um http resp ...
Se tslint / ide reclamar que o tipo de argumento é incompatível, basta converter o argumento no mesmo tipo usando colchetes angulares
<YourClassName>
, exemplo:Se você possui membros de classe de um tipo específico (aka: instância de outra classe), pode convertê-los em instâncias digitadas por meio de métodos getter / setter.
O exemplo acima desserializa o acct e a lista de tarefas em suas respectivas instâncias de classe.
fonte
Supondo que o json tenha as mesmas propriedades da sua classe de texto datilografado, você não precisará copiar suas propriedades Json para o seu objeto datilografado. Você apenas precisará construir seu objeto TypeScript passando os dados json no construtor.
No seu retorno de chamada ajax, você recebe uma empresa:
Para fazer esse trabalho:
1) Adicione um construtor em sua classe Typescript que tome os dados json como parâmetro. Nesse construtor você estender o seu objeto JSON com jQuery, como este:
$.extend( this, jsonData)
. $ .extend permite manter os protótipos javascript enquanto adiciona as propriedades do objeto json.2) Observe que você terá que fazer o mesmo para objetos vinculados. No caso de Funcionários no exemplo, você também cria um construtor que toma a parte dos dados json dos funcionários. Você chama $ .map para converter funcionários json em objetos de texto datilografados de Funcionário.
Esta é a melhor solução que encontrei ao lidar com classes Typescript e objetos json.
fonte
Ainda não há nada para verificar automaticamente se o objeto JSON que você recebeu do servidor possui as propriedades de interface do datilógrafo esperadas (a leitura está em conformidade com as). Mas você pode usar proteções de tipo definido pelo usuário
Considerando a seguinte interface e um objeto json bobo (poderia ter sido de qualquer tipo):
Três maneiras possíveis:
A. Asserção de tipo ou conversão estática simples colocada após a variável
B. Molde estático simples, antes da variável e entre diamantes
C. Elenco dinâmico avançado, você verifica a estrutura do objeto
Você pode brincar com este exemplo aqui
Observe que a dificuldade aqui é escrever a
isMyInterface
função. Espero que o TS adicione um decorador, mais cedo ou mais tarde, para exportar a digitação complexa para o tempo de execução e deixe o tempo de execução verificar a estrutura do objeto, quando necessário. Por enquanto, você pode usar um validador de esquema json cujo objetivo é aproximadamente o mesmo OU esse gerador de função de verificação de tipo de tempo de execuçãofonte
No meu caso, funciona. Eu usei as funções Object.assign (destino, fontes ...) . Primeiro, a criação do objeto correto e, em seguida, copia os dados do objeto json para o destino.
E um exemplo mais avançado de uso. Um exemplo usando a matriz.
fonte
this.users[i] = new User(); Object.assign(this.users[i], users[i])
this.users[i] = Object.assign(new User(), users[i]);
Enquanto não estiver lançando por si só; Eu achei https://github.com/JohnWhiteTB/TypedJSON uma alternativa útil.
fonte
Você pode criar um
interface
do seu tipo (SomeType
) e converter o objeto nisso.fonte
Se você precisar converter seu objeto json para uma classe de texto datilografado e ter seus métodos de instância disponíveis no objeto resultante que você precisa usar
Object.setPrototypeOf
, como eu fiz no trecho de código abaixo:fonte
Uma pergunta antiga com respostas principalmente corretas, mas não muito eficientes. Isto é o que eu proponho:
Crie uma classe base que contenha o método init () e métodos de conversão estática (para um único objeto e uma matriz). Os métodos estáticos podem estar em qualquer lugar; a versão com a classe base e init () permite extensões fáceis depois.
Mecânica semelhante (com assign () ) foi mencionada na publicação do @ Adam111p. Apenas outra maneira (mais completa) de fazer isso. @ Timothy Perez é crítico em relação a assign () , mas é totalmente apropriado aqui.
Implemente uma classe derivada (a real):
Agora podemos converter um objeto recuperado do serviço:
Toda a hierarquia de objetos SubjectArea terá a classe correta.
Um caso de uso / exemplo; crie um serviço Angular (classe base abstrata novamente):
O uso se torna muito simples; crie um serviço de área:
pegue() método do serviço retornará uma promessa de uma matriz já lançada como objetos SubjectArea (hierarquia inteira)
Agora digamos, temos outra classe:
Criar um serviço que recupera dados e lança para a classe correta é tão simples quanto:
fonte
Use uma classe estendida de uma interface.
Então:
E melhor:
O que se torna um controlador do DataInterface.
fonte
https://jvilk.com/MakeTypes/
você pode usar este site para gerar um proxy para você. ele gera uma classe e pode analisar e validar seu objeto JSON de entrada.
fonte
Nos últimos anos, você pode fazer o seguinte:
E que usuário como este:
fonte
Encontrei uma necessidade semelhante. Eu queria algo que me proporcionasse uma fácil transformação de / para JSON proveniente de uma chamada API REST de / para uma definição de classe específica. As soluções que encontrei eram insuficientes ou pretendiam reescrever o código das minhas aulas e adicionar anotações ou similares.
Eu queria que algo como o GSON fosse usado em Java para serializar / desserializar classes de / para objetos JSON.
Combinado com uma necessidade posterior, de que o conversor funcione também em JS, acabei escrevendo meu próprio pacote.
No entanto, tem um pouco de sobrecarga. Mas quando iniciado, é muito conveniente adicionar e editar.
Você inicializa o módulo com:
Então, no seu código, você usa o módulo inicializado como:
ou, para JSON:
Use este link para o pacote npm e também uma explicação detalhada de como trabalhar com o módulo: json-class-converter
Também o envolveu para
uso Angular em: angular-json-class-converter
fonte
Passe o objeto como está para o construtor da classe; Sem convenções ou verificações
fonte
Você pode usar este pacote npm. https://www.npmjs.com/package/class-converter
É fácil de usar, por exemplo:
fonte
Pessoalmente, acho espantoso que o texto datilografado não permita que uma definição de terminal especifique o tipo do objeto que está sendo recebido. Como parece que esse é realmente o caso, eu faria o que fiz com outras linguagens, separando o objeto JSON da definição de classe e fazendo com que a definição de classe usasse o objeto JSON como seu único membro de dados .
Eu desprezo o código padrão, portanto, para mim, geralmente é uma questão de obter o resultado desejado com a menor quantidade de código enquanto preservo o tipo.
Considere as seguintes definições de estrutura de objeto JSON - elas seriam o que você receberia em um nó de extremidade; elas são apenas definições de estrutura, sem métodos.
Se pensarmos no exposto em termos orientados a objetos, as interfaces acima não são classes porque definem apenas uma estrutura de dados. Uma classe em termos OO define dados e o código que opera neles.
Agora, definimos uma classe que especifica os dados e o código que opera neles ...
E agora podemos simplesmente passar qualquer objeto em conformidade com a estrutura IPerson e seguir nosso caminho ...
Da mesma forma, agora podemos processar o objeto recebido no seu endpoint com algo ao longo das linhas de ...
Isso tem muito mais desempenho e usa metade da memória de cópia dos dados, enquanto reduz significativamente a quantidade de código padrão que você deve escrever para cada tipo de entidade. Simplesmente conta com a segurança de tipo fornecida pelo TypeScript.
fonte
Use a declaração 'as':
fonte
MyClass
.Esta é uma opção simples e realmente boa
E então você terá
fonte
Usei esta biblioteca aqui: https://github.com/pleerock/class-transformer
Implementação:
Às vezes, você precisará analisar os valores JSON para plainToClass para entender que são dados formatados em JSON
fonte
Estou usando o Angular 6 no frontend e o aplicativo Spring Boot no backend, que retorna objetos Java. Tudo o que preciso fazer é definir uma classe semelhante no aplicativo angular que tenha propriedades correspondentes e então eu posso aceitar o objeto 'como' um objeto de classe angular ( comp como Company no exemplo abaixo).
Consulte o código de front-end abaixo, por exemplo. Deixe-me saber nos comentários se algo precisa de mais clareza.
em que empresa é um objeto de entidade no aplicativo de inicialização por primavera e também é uma classe em Angular.
fonte