Czytałem obiekt JSON ze zdalnego serwera REST. Ten obiekt JSON ma wszystkie właściwości klasy maszynopisu (według projektu). Jak rzutować otrzymany obiekt JSON na typ var?
Nie chcę wypełniać var maszynopisu (tj. Mieć konstruktor, który pobiera ten obiekt JSON). Jest duży, a kopiowanie wszystkiego między podobiektami według podobiektów i właściwości według właściwości zajęłoby dużo czasu.
Aktualizacja: Możesz jednak rzucić go na interfejs maszynopisu!
json
typescript
David Thielen
źródło
źródło
Odpowiedzi:
Nie można w prosty sposób rzutować wyniku zwykłego starego kodu JavaScript z żądania Ajax na prototypową instancję klasy JavaScript / TypeScript. Można to zrobić na wiele sposobów i zazwyczaj wiąże się to z kopiowaniem danych. O ile nie utworzysz instancji klasy, nie będzie ona miała żadnych metod ani właściwości. Pozostanie prostym obiektem JavaScript.
Chociaż jeśli masz do czynienia tylko z danymi, możesz po prostu wykonać rzutowanie do interfejsu (ponieważ jest to wyłącznie struktura czasowa kompilacji), wymagałoby to użycia klasy TypeScript, która korzysta z instancji danych i wykonuje operacje na tych danych.
Kilka przykładów kopiowania danych:
Zasadniczo po prostu:
źródło
JSON.parse()
. Oba nadal będą musiały zostać wykonane, ale pod względem składniowym można je połączyć.Object.setPrototypeOf
Miałem ten sam problem i znalazłem bibliotekę wykonującą to zadanie: https://github.com/pleerock/class-transformer .
Działa to tak:
Obsługuje zagnieżdżone dzieci, ale musisz udekorować członka swojej klasy.
źródło
@Type
choć nie zapomnij o swoich adnotacjach). Ta odpowiedź zasługuje na większe uznanie.W TypeScript można wykonać asercję typu za pomocą interfejsu i ogólnych:
Gdzie ILocationMap opisuje kształt twoich danych. Zaletą tej metody jest to, że JSON może zawierać więcej właściwości, ale kształt spełnia warunki interfejsu.
Mam nadzieję że to pomogło!
źródło
Jeśli używasz ES6, spróbuj tego:
Niestety ten sposób nie będzie działał na obiekcie gniazdowym .
źródło
Object.create(MyClass.prototype)
, pomijając konstruktor.Znalazłem bardzo interesujący artykuł na temat ogólnego rzutowania JSON na klasę maszynopisu:
http://cloudmark.github.io/Json-Mapping/
Otrzymasz następujący kod:
źródło
TLDR: Jedna wkładka
Szczegółowa odpowiedź
Nie zrobiłbym tego polecam Object.assign podejście, ponieważ może niewłaściwie miot czy instancja klasy o właściwościach nieistotnych (jak zdefiniowano zamknięcia), które nie zostały zgłoszone w ramach samej klasie.
W klasie, w której próbujesz deserializować, upewniłbym się, że zdefiniowane są wszystkie właściwości, które chcesz deserializować (null, pusta tablica itp.). Definiując swoje właściwości za pomocą wartości początkowych, ujawniasz ich widoczność podczas próby iteracji członków klasy w celu przypisania wartości (patrz metoda deserializacji poniżej).
W powyższym przykładzie po prostu utworzyłem metodę deserializacji. W prawdziwym przykładzie chciałbym, aby był scentralizowany w klasie bazowej lub metodzie usługi wielokrotnego użytku.
Oto, jak wykorzystać to w czymś takim jak http resp ...
Jeśli tslint / ide skarży się na niezgodność typu argumentu, wystarczy rzutować argument na ten sam typ za pomocą nawiasów kątowych
<YourClassName>
, przykład:Jeśli masz członków klasy, które są określonego typu (aka: wystąpienie innej klasy), możesz ich rzutować na wpisane wystąpienia za pomocą metod getter / setter.
Powyższy przykład deserializuje zarówno acct, jak i listę zadań do odpowiednich instancji klas.
źródło
Zakładając, że json ma takie same właściwości jak klasa maszynopisu, nie musisz kopiować właściwości Json do obiektu maszynopisu. Musisz tylko zbudować obiekt Typescript przekazując dane json w konstruktorze.
W wywołaniu zwrotnym ajax otrzymujesz firmę:
Aby to zadziałało:
1) Dodaj konstruktor do klasy Typescript, który przyjmuje dane json jako parametr. W tym konstruktora przedłużyć swój obiekt json z jQuery, jak ten:
$.extend( this, jsonData)
. $ .extend pozwala zachować prototypy javascript podczas dodawania właściwości obiektu json.2) Pamiętaj, że musisz zrobić to samo dla połączonych obiektów. W przypadku pracowników w tym przykładzie tworzony jest również konstruktor, który pobiera część danych json dla pracowników. Wywołujesz $ .map, aby tłumaczyć pracowników json na maszynopis obiektów pracowników.
To najlepsze rozwiązanie, jakie znalazłem podczas pracy z klasami Typescript i obiektami json.
źródło
Nie ma jeszcze nic, aby automatycznie sprawdzić, czy obiekt JSON otrzymany z serwera ma oczekiwane (zgodne z) właściwości interfejsu maszynopisu. Możesz jednak użyć zdefiniowanych przez użytkownika osłon typu
Biorąc pod uwagę następujący interfejs i głupiutki obiekt Json (mógł to być dowolny typ):
Trzy możliwe sposoby:
A. Typ Asercja lub zwykły rzut statyczny umieszczony za zmienną
B. Proste odlewanie statyczne, przed zmienną i między diamentami
C. Zaawansowany rzut dynamiczny, sam sprawdzasz strukturę obiektu
Możesz grać z tym przykładem tutaj
Zauważ, że trudność polega na napisaniu
isMyInterface
funkcji. Mam nadzieję, że TS prędzej czy później doda dekorator, aby wyeksportować złożone pisanie do środowiska wykonawczego i pozwolić środowisku wykonawczemu sprawdzić strukturę obiektu w razie potrzeby. Na razie możesz użyć walidatora schematu json, którego przeznaczenie jest w przybliżeniu takie samo LUB tego generatora funkcji sprawdzania typu środowiska wykonawczegoźródło
W moim przypadku to działa. Użyłem funkcji Object.assign (target, źródła ...) . Najpierw utworzenie poprawnego obiektu, a następnie skopiowanie danych z obiektu json do obiektu docelowego. Przykład:
I bardziej zaawansowany przykład użycia. Przykład z wykorzystaniem tablicy.
źródło
this.users[i] = new User(); Object.assign(this.users[i], users[i])
this.users[i] = Object.assign(new User(), users[i]);
Chociaż samo w sobie nie rzuca; Znalazłem https://github.com/JohnWhiteTB/TypedJSON jako przydatną alternatywę.
źródło
Możesz utworzyć
interface
swój typ (SomeType
) i rzucić w niego obiekt.źródło
Jeśli chcesz rzutować obiekt json na klasę maszynopisu i mieć dostępne metody instancji w obiekcie wynikowym, którego musisz użyć
Object.setPrototypeOf
, tak jak zrobiłem to w poniższym fragmencie kodu:źródło
Stare pytanie z najczęściej poprawnymi, ale niezbyt skutecznymi odpowiedziami. Oto co proponuję:
Utwórz klasę podstawową, która zawiera metodę init () i metody rzutowania statycznego (dla pojedynczego obiektu i tablicy). Metody statyczne mogą być wszędzie; wersja z klasą bazową i init () pozwala później na łatwe rozszerzenia.
Podobne mechanizmy (z przypisaniem () ) zostały wspomniane w poście @ Adam111p. Po prostu kolejny (bardziej kompletny) sposób na zrobienie tego. @Timothy Perez krytycznie odnosi się do przypisania () , ale imho jest tutaj w pełni odpowiednie.
Zaimplementuj pochodną (prawdziwą) klasę:
Teraz możemy rzutować obiekt pobrany z usługi:
Cała hierarchia obiektów SubjectArea będzie miała poprawną klasę.
Przypadek użycia / przykład; utwórz usługę Angular (abstrakcyjna klasa podstawowa ponownie):
Użycie staje się bardzo proste; utwórz usługę obszaru:
Metoda get () usługi zwróci obietnicę tablicy już rzutowanej jako obiekty SubjectArea (cała hierarchia)
Powiedzmy, że mamy inną klasę:
Tworzenie usługi, która pobiera dane i rzutuje do odpowiedniej klasy, jest tak proste, jak:
źródło
Użyj klasy rozszerzonej z interfejsu.
Następnie:
A najlepiej:
ToWhat staje się kontrolerem DataInterface.
źródło
https://jvilk.com/MakeTypes/
możesz użyć tej strony do wygenerowania proxy. generuje klasę i może analizować i sprawdzać wejściowy obiekt JSON.
źródło
W Lates TS możesz to zrobić w następujący sposób:
A niż użytkownik taki:
źródło
Wpadłem na podobną potrzebę. Chciałem czegoś, co da mi łatwą transformację z / do JSON, która pochodzi z wywołania interfejsu API REST do / z określonej definicji klasy. Rozwiązania, które znalazłem, były niewystarczające lub miały na celu przepisanie kodu moich klas i dodanie adnotacji lub podobnych.
Chciałem, aby coś takiego jak GSON było używane w Javie do serializacji / deserializacji klas do / z obiektów JSON.
W połączeniu z późniejszą potrzebą, aby konwerter działał również w JS, skończyłem pisać własny pakiet.
Ma jednak trochę narzutów. Ale po uruchomieniu jest bardzo wygodne w dodawaniu i edytowaniu.
Inicjujesz moduł za pomocą:
Następnie w kodzie używasz zainicjowanego modułu, takiego jak:
lub do JSON:
Skorzystaj z tego łącza do pakietu npm, a także szczegółowe wyjaśnienie, jak pracować z modułem: konwerter json
Zapakowałem go również do
użytku Angular w: konwerter angular-json-class
źródło
Przekaż obiekt bez zmian konstruktorowi klasy; Brak konwencji lub kontroli
źródło
Możesz użyć tego pakietu npm. https://www.npmjs.com/package/class-converter
Jest łatwy w użyciu, na przykład:
źródło
Osobiście uważam za przerażające, że maszynopis nie pozwala definicji punktu końcowego określić typu otrzymywanego obiektu. Wygląda na to, że tak właśnie jest, zrobiłbym to, co zrobiłem z innymi językami, i oddzieliłbym obiekt JSON od definicji klasy, a definicja klasy użyłaby obiektu JSON jako jedynego elementu danych .
Nienawidzę kodu, który jest dla mnie bardzo ważny, więc dla mnie zazwyczaj chodzi o osiągnięcie pożądanego rezultatu przy najmniejszej ilości kodu przy zachowaniu typu.
Rozważ następujące definicje struktury obiektów JSON - byłyby to te, które otrzymasz w punkcie końcowym, są to tylko definicje struktury, bez metod.
Jeśli myślimy o powyższym w kategoriach obiektowych, powyższe interfejsy nie są klasami, ponieważ definiują jedynie strukturę danych. Klasa w kategoriach OO definiuje dane i kod, który na nich działa.
Definiujemy teraz klasę, która określa dane i działający na niej kod ...
A teraz możemy po prostu przekazać dowolny obiekt zgodny ze strukturą IPerson i być w drodze ...
W ten sam sposób możemy teraz przetwarzać obiekt otrzymany w twoim punkcie końcowym za pomocą czegoś podobnego do ...
Jest to o wiele bardziej wydajne i zużywa połowę pamięci na kopiowanie danych, przy jednoczesnym znacznym zmniejszeniu ilości kodu, który musisz napisać dla każdego typu encji. Po prostu polega na bezpieczeństwie typu zapewnianym przez TypeScript.
źródło
Użyj deklaracji „jako”:
źródło
MyClass
.Jest to prosta i naprawdę dobra opcja
A potem będziesz miał
źródło
Korzystałem z tej biblioteki tutaj: https://github.com/pleerock/class-transformer
Realizacja:
Czasami trzeba przeanalizować wartości JSON dla plainToClass, aby zrozumieć, że są to dane sformatowane w JSON
źródło
Korzystam z Angular 6 w interfejsie i aplikacji Spring Boot w backend, która zwraca obiekty Java. Wszystko, co muszę zrobić, to zdefiniować podobną klasę w aplikacji kątowej, która ma pasujące właściwości, a następnie mogę zaakceptować obiekt „jako” obiekt klasy kątowej ( porównaj jako Company w poniższym przykładzie).
Patrz na przykład kod interfejsu użytkownika poniżej. Daj mi znać w komentarzach, jeśli coś wymaga większej przejrzystości.
gdzie firma jest obiektem encji w wiosennej aplikacji rozruchowej, a także klasą w Angular.
źródło