J'ai lu un objet JSON à partir d'un serveur REST distant. Cet objet JSON a toutes les propriétés d'une classe dactylographiée (par conception). Comment convertir cet objet JSON reçu en un type var?
Je ne veux pas remplir une var dactylographiée (c'est-à-dire avoir un constructeur qui prend cet objet JSON). Il est grand et tout copier sous-objet par sous-objet et propriété par propriété prendrait beaucoup de temps.
Mise à jour: Vous pouvez cependant le diffuser sur une interface dactylographiée!
json
typescript
David Thielen
la source
la source
Réponses:
Vous ne pouvez pas simplement convertir un résultat JavaScript purement ancien d'une demande Ajax en une instance de classe JavaScript / TypeScript prototypique. Il existe un certain nombre de techniques pour le faire et impliquent généralement la copie de données. À moins que vous ne créiez une instance de la classe, elle n'aura aucune méthode ou propriété. Il restera un simple objet JavaScript.
Alors que si vous ne traitiez que des données, vous pouvez simplement effectuer un cast vers une interface (car il s'agit purement d'une structure de temps de compilation), cela nécessiterait que vous utilisiez une classe TypeScript qui utilise l'instance de données et effectue des opérations avec ces données.
Quelques exemples de copie des données:
En substance, vous voudriez juste:
la source
JSON.parse()
. Les deux devraient encore être effectués, mais syntaxiquement, ils pourraient être combinés.Object.setPrototypeOf
J'ai eu le même problème et j'ai trouvé une bibliothèque qui fait le travail: https://github.com/pleerock/class-transformer .
Cela fonctionne comme ceci:
Il prend en charge les enfants imbriqués, mais vous devez décorer le membre de votre classe.
la source
@Type
annotations, cependant). Cette réponse mérite plus de crédit.Dans TypeScript, vous pouvez faire une assertion de type en utilisant une interface et des génériques comme ceci:
Où ILocationMap décrit la forme de vos données. L'avantage de cette méthode est que votre JSON peut contenir plus de propriétés mais la forme satisfait les conditions de l'interface.
J'espère que ça aide!
la source
Si vous utilisez ES6, essayez ceci:
Malheureusement, cette méthode ne fonctionnera pas sur l'objet nid .
la source
Object.create(MyClass.prototype)
, en contournant complètement le constructeur.J'ai trouvé un article très intéressant sur la conversion générique de JSON en classe Typescript:
http://cloudmark.github.io/Json-Mapping/
Vous vous retrouvez avec le code suivant:
la source
TLDR: une doublure
La réponse détaillée
Je ne recommanderais pas l'approche Object.assign, car elle peut joncher de manière inappropriée votre instance de classe avec des propriétés non pertinentes (ainsi que des fermetures définies) qui n'ont pas été déclarées dans la classe elle-même.
Dans la classe dans laquelle vous essayez de désérialiser, je m'assurerais que toutes les propriétés que vous souhaitez désérialiser soient définies (null, tableau vide, etc.). En définissant vos propriétés avec des valeurs initiales, vous exposez leur visibilité lorsque vous essayez d'itérer des membres de classe auxquels affecter des valeurs (voir la méthode de désérialisation ci-dessous).
Dans l'exemple ci-dessus, j'ai simplement créé une méthode de désérialisation. Dans un exemple réel, je l'aurais centralisé dans une classe de base réutilisable ou une méthode de service.
Voici comment l'utiliser dans quelque chose comme un http resp ...
Si tslint / ide se plaint que le type d'argument est incompatible, il suffit de transposer l'argument dans le même type à l'aide de crochets angulaires
<YourClassName>
, exemple:Si vous avez des membres de classe qui sont d'un type spécifique (aka: instance d'une autre classe), vous pouvez les faire transtyper en instances typées via des méthodes getter / setter.
L'exemple ci-dessus désérialise à la fois acct et la liste des tâches dans leurs instances de classe respectives.
la source
En supposant que json a les mêmes propriétés que votre classe dactylographiée, vous n'avez pas à copier vos propriétés Json dans votre objet dactylographié. Il vous suffira de construire votre objet Typescript en passant les données json dans le constructeur.
Dans votre rappel ajax, vous recevez une entreprise:
Pour que cela fonctionne:
1) Ajoutez un constructeur dans votre classe Typescript qui prend les données json comme paramètre. Dans ce constructeur vous étendez votre objet JSON avec jQuery, comme ceci:
$.extend( this, jsonData)
. $ .extend permet de conserver les prototypes javascript tout en ajoutant les propriétés de l'objet json.2) Notez que vous devrez faire de même pour les objets liés. Dans le cas des employés dans l'exemple, vous créez également un constructeur prenant la partie des données json pour les employés. Vous appelez $ .map pour traduire les employés json en objets employés dactylographiés.
C'est la meilleure solution que j'ai trouvée en traitant des classes Typescript et des objets json.
la source
Il n'y a encore rien à vérifier automatiquement si l'objet JSON que vous avez reçu du serveur a les propriétés d'interface attendues (la lecture est conforme aux) typescript. Mais vous pouvez utiliser des gardes de type définis par l'utilisateur
Considérant l'interface suivante et un objet json idiot (il aurait pu être de n'importe quel type):
Trois voies possibles:
A. Type Assertion ou distribution statique simple placée après la variable
B. Fonte statique simple, avant la variable et entre les diamants
C. Cast dynamique avancé, vous vérifiez vous-même la structure de l'objet
Vous pouvez jouer avec cet exemple ici
Notez que la difficulté ici est d'écrire la
isMyInterface
fonction. J'espère que TS ajoutera tôt ou tard un décorateur pour exporter la saisie complexe vers le runtime et laisser le runtime vérifier la structure de l'objet en cas de besoin. Pour l'instant, vous pouvez soit utiliser un validateur de schéma json dont le but est approximativement le même OU ce générateur de fonction de vérification du type d'exécutionla source
Dans mon cas, cela fonctionne. J'ai utilisé les fonctions Object.assign (cible, sources ...) . Tout d'abord, la création de l'objet correct, puis copie les données de l'objet json vers la cible.
Et un exemple d'utilisation plus avancé. Un exemple utilisant le tableau.
la source
this.users[i] = new User(); Object.assign(this.users[i], users[i])
this.users[i] = Object.assign(new User(), users[i]);
Bien qu'il ne soit pas un casting en soi; J'ai trouvé que https://github.com/JohnWhiteTB/TypedJSON était une alternative utile.
la source
Vous pouvez créer un
interface
de votre type (SomeType
) et y insérer l'objet.la source
Si vous devez convertir votre objet json en une classe dactylographiée et avoir ses méthodes d'instance disponibles dans l'objet résultant que vous devez utiliser
Object.setPrototypeOf
, comme je l'ai fait dans l'extrait de code ci-dessous:la source
Une vieille question avec des réponses généralement correctes mais pas très efficaces. Voici ce que je propose:
Créez une classe de base qui contient la méthode init () et les méthodes de transtypage statiques (pour un seul objet et un tableau). Les méthodes statiques peuvent être n'importe où; la version avec la classe de base et init () permet ensuite des extensions faciles.
Des mécanismes similaires (avec assign () ) ont été mentionnés dans @ Adam111p post. Juste une autre façon (plus complète) de le faire. @Timothy Perez critique critique assign () , mais à mon humble avis, il est tout à fait approprié ici.
Implémentez une classe dérivée (la vraie):
Maintenant, nous pouvons lancer un objet récupéré du service:
Toutes les hiérarchies d' objets SubjectArea auront la classe correcte.
Un cas d'utilisation / exemple; créer un service angulaire (classe de base abstraite à nouveau):
L'utilisation devient très simple; créer un service Area:
La méthode get () du service renverra une promesse d'un tableau déjà converti en objets SubjectArea (hiérarchie entière)
Maintenant, disons, nous avons une autre classe:
La création d'un service qui récupère les données et les convertit dans la classe correcte est aussi simple que:
la source
Utilisez une classe étendue à partir d'une interface.
Alors:
Et mieux:
ToWhat devient un contrôleur de DataInterface.
la source
https://jvilk.com/MakeTypes/
vous pouvez utiliser ce site pour générer un proxy pour vous. il génère une classe et peut analyser et valider votre objet JSON d'entrée.
la source
Dans le lates TS, vous pouvez faire comme ceci:
Et que l'utilisateur comme ça:
la source
J'ai rencontré un besoin similaire. Je voulais quelque chose qui me donnera une transformation facile de / vers JSON qui provient d'un appel d'API REST vers / depuis une définition de classe spécifique. Les solutions que j'ai trouvées étaient insuffisantes ou destinées à réécrire le code de mes classes et à ajouter des annotations ou similaires.
Je voulais que quelque chose comme GSON soit utilisé en Java pour sérialiser / désérialiser les classes vers / depuis les objets JSON.
Combiné avec un besoin ultérieur, que le convertisseur fonctionnera également dans JS, j'ai fini d'écrire mon propre package.
Il a cependant, un peu de frais généraux. Mais au démarrage, il est très pratique pour l'ajout et l'édition.
Vous initialisez le module avec:
Ensuite, dans votre code, vous utilisez le module initialisé comme:
ou, vers JSON:
Utilisez ce lien vers le package npm et également une explication détaillée sur la façon de travailler avec le module: json-class-converter
Également enveloppé pour une
utilisation angulaire dans: convertisseur de classe json angulaire
la source
Passez l'objet tel quel au constructeur de classe; Pas de conventions ni de contrôles
la source
Vous pouvez utiliser ce package npm. https://www.npmjs.com/package/class-converter
Il est facile à utiliser, par exemple:
la source
Personnellement, je trouve épouvantable que dactylographié ne permette pas à une définition de point de terminaison de spécifier le type de l'objet reçu. Comme il semble que ce soit effectivement le cas, je ferais ce que j'ai fait avec d'autres langages, c'est-à-dire que je séparerais l'objet JSON de la définition de classe et que la définition de classe utilise l'objet JSON comme seul membre de données .
Je méprise le code passe-partout, donc pour moi, il s'agit généralement d'obtenir le résultat souhaité avec le moins de code possible tout en préservant le type.
Considérez les définitions de structure d'objet JSON suivantes - ce serait ce que vous recevriez à un point de terminaison, ce ne sont que des définitions de structure, pas de méthodes.
Si nous considérons ce qui précède en termes orientés objet, les interfaces ci-dessus ne sont pas des classes car elles ne définissent qu'une structure de données. Une classe en termes OO définit les données et le code qui les opère.
Nous définissons donc maintenant une classe qui spécifie les données et le code qui les opère ...
Et maintenant, nous pouvons simplement passer n'importe quel objet conforme à la structure IPerson et être en route ...
De la même manière, nous pouvons maintenant traiter l'objet reçu à votre point d'extrémité avec quelque chose comme ...
Ceci est beaucoup plus performant et utilise la moitié de la mémoire de copie des données, tout en réduisant considérablement la quantité de code standard que vous devez écrire pour chaque type d'entité. Il repose simplement sur la sécurité des types fournie par TypeScript.
la source
Utilisez la déclaration 'as':
la source
MyClass
.C'est une option simple et vraiment bonne
Et puis vous aurez
la source
J'ai utilisé cette bibliothèque ici: https://github.com/pleerock/class-transformer
La mise en oeuvre:
Parfois, vous devrez analyser les valeurs JSON pour plainToClass pour comprendre qu'il s'agit de données au format JSON
la source
J'utilise Angular 6 sur le frontend et l'application Spring Boot sur le backend qui renvoie les objets Java. Tout ce que je dois faire est de définir une classe similaire sur l'application angulaire qui a des propriétés correspondantes, puis je peux accepter l'objet «comme» un objet de classe angulaire ( comp comme Company dans l'exemple ci-dessous).
Reportez-vous au code frontal ci-dessous par exemple. Faites-moi savoir dans les commentaires si quelque chose a besoin de plus de clarté.
où entreprise est un objet entité dans l'application Spring Boot et est également une classe en angulaire.
la source