Bir JSON nesnesini daktilo sınıfına nasıl atabilirim


393

Uzak bir REST sunucusundan bir JSON nesnesi okudum. Bu JSON nesnesi, bir daktilo sınıfının (tasarım gereği) tüm özelliklerine sahiptir. Bu JSON nesnesini bir var değişkenine nasıl atabilirim?

Bir typescript var doldurmak istemiyorum (yani bu JSON nesnesini alır bir yapıcı var). Büyüktür ve her şeyi alt nesneye alt nesne ve özellik tarafından mülk ile kopyalamak çok zaman alacaktır.

Güncelleme: Ancak bir daktilo arabirimine yayınlayabilirsiniz!


JSON'unuzun Java sınıfları kullanılarak eşlenmesi durumunda TypeScript arabirimleri oluşturmak için github.com/vojtechhabarta/typescript-generator kullanabilirsiniz
Vojta

: Ben küçük bir döküm kütüphane kodlu ettik sulphur-blog.azurewebsites.net/typescript-mini-cast-library
Camille Wintz

1
JSON object = JavaScript Nesne Gösterim nesnesi. İçinde yeterince nesne yok, iyi ölçü için birkaç tane daha attığımızı söylüyorum.
bug-a-lot


Nesnenizi tanımlamak için prototip TypeScript sınıfı oluşturmak gerçek üretim koduna zarar vermez. Derlenmiş JS dosyasına bir bakın, JS'nin bir parçası olmadığı için tüm tanımlar kaldırılacaktır.
FisNaN

Yanıtlar:


167

Ajax isteğindeki düz eski bir JavaScript sonucunu prototipik bir JavaScript / TypeScript sınıfı örneğine basitçe atayamazsınız. Bunu yapmak için bir takım teknikler vardır ve genellikle veri kopyalamayı içerir. Sınıfın bir örneğini oluşturmadığınız sürece, herhangi bir yöntemi veya özelliği olmayacaktır. Basit bir JavaScript nesnesi olarak kalacaktır.

Yalnızca verilerle uğraşıyorsanız, yalnızca bir arayüze yayın yapabilirsiniz (yalnızca derleme zamanı yapısı olduğu için), bu, veri örneğini kullanan ve bu verilerle işlemler gerçekleştiren bir TypeScript sınıfı kullanmanızı gerektirir.

Verileri kopyalamaya bazı örnekler:

  1. AJAX JSON nesnesini mevcut Nesneye kopyalama
  2. JavaScript'te JSON Dizesini Belirli Bir Nesne Prototipe Ayrıştırma

Özünde, sadece:

var d = new MyRichObject();
d.copyInto(jsonResult);

Cevabınıza katılıyorum. Ek olarak, şu anda bakmak ve test etmek için bir yerde olmamam rağmen, bu iki adımın bir param olarak uyandırma işlevi vererek birleştirilebileceğini düşünüyorum JSON.parse(). Her ikisinin de yapılması gerekiyordu, ancak sözdizimsel olarak birleştirilebilirler.
JAAulde

Elbette, bu da işe yarayabilir - Her özellik için ekstra bir işlev çağrısı çağırması gerekeceğinden daha verimli olup olmayacağı konusunda bir fikrim yok.
WiredPrairie

Kesinlikle aradığım cevap değil :( meraktan dolayı neden bu? Bana öyle geliyor ki javascript bu şekilde olması gerektiği gibi çalışır.
David Thielen

Hayır, JavaScript'te bunu yapmanın basit bir yolu olmadığından, TypeScript'te çalışmaz.
WiredPrairie

1
Ne dersinObject.setPrototypeOf
Petah

102

Aynı sorunu yaşadım ve işi yapan bir kütüphane buldum: https://github.com/pleerock/class-transformer .

Şöyle çalışır:

let jsonObject = response.json() as Object;
let fooInstance = plainToClass(Models.Foo, jsonObject);
return fooInstance;

İç içe geçmiş çocukları destekler ancak sınıf üyenizi süslemeniz gerekir.


14
Bu parlak küçük kütüphane, en az çaba ile mükemmel bir şekilde çözdü ( @Typeek açıklamalarınızı unutmayın ). Bu Yanıt daha fazla krediyi hak ediyor.
Benny Bottema

Vay canına !, bu kütüphane belki de ihtiyacınız olan her şeye sahip o kadar küçük değil, dönüşümü @transform decorator ile kontrol etmenize bile izin veriyor: D
Diego Fernando Murillo

3
Bu kütüphanenin artık zar zor muhafaza edildiğini unutmayın. Artık Angular5 + ile çalışmıyor ve artık çekme isteklerini birleştirmedikleri için, yakında bu konuda çalışacaklarını sanmıyorum. Yine de harika bir kütüphane.
kentor

Angular5 + için bir geçici çözüm var (aslında bir Açısal Hata): github.com/typestack/class-transformer/issues/108
Pak

2
Bu Açısal 6'da iyi çalışıyor (en azından kelimenin tam anlamıyla JSON <=> Sınıfını haritalamak için kullanım
durumum için

54

TypeScript'te, bir arabirim ve şöyle jenerikler kullanarak bir tür iddiası yapabilirsiniz :

var json = Utilities.JSONLoader.loadFromFile("../docs/location_map.json");
var locations: Array<ILocationMap> = JSON.parse(json).location;

Burada ILocationMap verilerinizin şeklini tanımlar. Bu yöntemin avantajı, JSON'unuzun daha fazla özellik içerebilmesi ancak şeklin arabirimin koşullarını karşılamasıdır.

Umarım bu yardımcı olur!


49
FYI: Bu bir tür iddia, oyuncu kadrosu değil.
WiredPrairie

6
Bir tür beyanı ve bir döküm arasındaki fark için buraya bakın .
Stefan Hanke

7
Utilities.JSONLoader'ı nerede bulabilirim?
HypeXR

22
Ancak cevapta belirtildiği gibi herhangi bir yöntemi olmayacaktır.
Martín Coll

1
@StefanHanke, URL'nin biraz değiştiğine benziyor: "Tür Onayı ve Döküm"
ruffin

37

ES6 kullanıyorsanız şunu deneyin:

class Client{
  name: string

  displayName(){
    console.log(this.name)
  }
}

service.getClientFromAPI().then(clientData => {

  // Here the client data from API only have the "name" field
  // If we want to use the Client class methods on this data object we need to:
  let clientWithType = Object.assign(new Client(), clientData)

  clientWithType.displayName()
})

Ancak bu şekilde yuva nesnesi üzerinde maalesef çalışmaz .


4
Daktilo yazısında istediler.
joe.feser

HI @ joe.feser, ES6'dan bahsediyorum çünkü bu şekilde 'Object.assign' yöntemi gereklidir.
migcoder

1
Varsayılan kurucunun eksik olması durumunda Object.create(MyClass.prototype), kurucu tamamen atlanarak hedef örnek oluşturulabilir .
Marcello

İç içe nesne sınırlaması hakkında daha fazla açıklama için bkz. Stackoverflow.com/questions/22885995/…
Michael Freidgeim

28

Bir JScript sınıfına JSON genel döküm hakkında çok ilginç bir makale buldum:

http://cloudmark.github.io/Json-Mapping/

Sonunda aşağıdaki kodla karşılaşırsınız:

let example = {
                "name": "Mark", 
                "surname": "Galea", 
                "age": 30, 
                "address": {
                  "first-line": "Some where", 
                  "second-line": "Over Here",
                  "city": "In This City"
                }
              };

MapUtils.deserialize(Person, example);  // custom class

20

TLDR: Bir astar

// This assumes your constructor method will assign properties from the arg.
.map((instanceData: MyClass) => new MyClass(instanceData));

Detaylı Cevap

Ben ediyorum değil o sınıfın kendi içinde uygunsuz çöp sınıf alakasız özelliklere sahip örneği (yanı sıra tanımlanan kapanışları) ilan edilmedi ki gibi Object.assign yaklaşımı öneriyoruz.

Seriden serileştirmeye çalıştığınız sınıfta, serileştirilmesini istediğiniz özelliklerin tanımlandığından emin olurum (boş, boş dizi, vb.). Özelliklerinizi başlangıç ​​değerleriyle tanımlayarak, sınıf üyelerini değer atamak için yinelemeye çalışırken görünürlüklerini ortaya koyarsınız (aşağıdaki seriyi kaldırma yöntemine bakın).

export class Person {
  public name: string = null;
  public favoriteSites: string[] = [];

  private age: number = null;
  private id: number = null;
  private active: boolean;

  constructor(instanceData?: Person) {
    if (instanceData) {
      this.deserialize(instanceData);
    }
  }

  private deserialize(instanceData: Person) {
    // Note this.active will not be listed in keys since it's declared, but not defined
    const keys = Object.keys(this);

    for (const key of keys) {
      if (instanceData.hasOwnProperty(key)) {
        this[key] = instanceData[key];
      }
    }
  }
}

Yukarıdaki örnekte, sadece bir serileştirme yöntemi oluşturdum. Gerçek bir dünya örneğinde, yeniden kullanılabilir bir temel sınıf veya hizmet yönteminde merkezileştirirdim.

İşte http resp gibi bir şey bu nasıl kullanılır ...

this.http.get(ENDPOINT_URL)
  .map(res => res.json())
  .map((resp: Person) => new Person(resp) ) );

Tslint / ide argüman türünün uyumsuz olduğundan şikayet ederse, köşeli parantez kullanarak argümanı aynı türe dönüştürün <YourClassName>, örnek:

const person = new Person(<Person> { name: 'John', age: 35, id: 1 });

Belirli bir türden sınıf üyeleriniz varsa (aka: başka bir sınıfın örneği), bunları getter / setter yöntemleri aracılığıyla yazılan örneklere döküm ettirebilirsiniz.

export class Person {
  private _acct: UserAcct = null;
  private _tasks: Task[] = [];

  // ctor & deserialize methods...

  public get acct(): UserAcct {
    return this.acct;
  }
  public set acct(acctData: UserAcct) {
    this._acct = new UserAcct(acctData);
  }

  public get tasks(): Task[] {
    return this._tasks;
  }

  public set tasks(taskData: Task[]) {
    this._tasks = taskData.map(task => new Task(task));
  }
}

Yukarıdaki örnek, ilgili sınıf örneklerine hem acct hem de görev listesini serileştirecektir.


Bu hata iletisini alıyorum: '{name: string, age: number, id: number}' yazın 'Kişi' türüne dönüştürülemiyor. 'İd' özelliği 'Kişi' türünde özel, ancak '{name: string, age: number, id: number}'
utiq

Bunu numaralandırmalarla nasıl kullanmalıyım? Spesifik tip yaklaşımını kullanmam ve bunun için alıcı ve ayarlayıcı eklemem gerekir mi?
Tadija Bagarić

@TimothyParez Görevleri ne zaman belirlersiniz?
Kay

Ben benzer bir şey yapmaya çalıştım ama i console.log kişi zaman benim görevler dizisi boş.
Kay

Bunu derlemek için sınıfa bir İndeks İmzası eklemek zorunda kaldım: export class Person {[key: string]: any (...)}
Asimov

18

Json'un typescript sınıfınızla aynı özelliklere sahip olduğunu varsayarsak, Json özelliklerinizi typescript nesnenize kopyalamanız gerekmez. Yapımcıdaki json verilerini geçirerek Typescript nesnenizi oluşturmanız yeterlidir.

Ajax geri çağrınızda bir şirket alırsınız:

onReceiveCompany( jsonCompany : any ) 
{
   let newCompany = new Company( jsonCompany );

   // call the methods on your newCompany object ...
}

Bu işi yapmak için:

1) Typescript sınıfınıza json verilerini parametre olarak alan bir kurucu ekleyin. Bu Yapıcıda böyle, jQuery ile json nesnesi uzatmak: $.extend( this, jsonData). $ .extend, json nesnesinin özelliklerini eklerken javascript prototiplerinin korunmasına izin verir.

2) Bağlantılı nesneler için de aynısını yapmanız gerektiğini unutmayın. Örnekteki Çalışanlar söz konusu olduğunda, çalışanlar için json verilerinin bir kısmını alan bir kurucu da oluşturursunuz. Json çalışanlarını, çalışan metni nesnelerine çevirmek için $ .map öğesini çağırırsınız.

export class Company
{
    Employees : Employee[];

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

        if ( jsonData.Employees )
            this.Employees = $.map( jsonData.Employees , (emp) => {
                return new Employee ( emp );  });
    }
}

export class Employee
{
    name: string;
    salary: number;

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

Bu, Typescript sınıfları ve json nesneleriyle uğraşırken bulduğum en iyi çözüm.


Bu çözümü arayüzleri uygulamak ve sürdürmek yerine tercih ediyorum, çünkü Angular2 uygulamalarımın, uygulamamın kullandığı web hizmetlerinin modelinden farklı olabilecek gerçek bir uygulama modeli var. Özel verilere ve hesaplanan özelliklere sahip olabilir.
Anthony Brenelière

7
Açısal projelerde JQuery kullanmak korkunç bir fikirdir. Ve modelleriniz üzerinde bir sürü işlev içeriyorsa, artık model değildir.
Davor

1
@Davor Yani POJO mu, model mi? POJO'nun (temelde düz nesnelerin) işlevleri yoktur, ancak model daha geniş bir terimdir ve depo içerir. Depo deseni, POJO'nun aksine, işlevlerle ilgilidir, ancak yine de modeldir.
forsberg

@Davor: Açısal projelerde JQuery kullanmak, gerçekten korkunç bir fikir olan DOM'u manipüle etmek için kullanmadığınız sürece kötü bir fikir değildir. Açısal projelerim için ihtiyacım olan herhangi bir kütüphaneyi kullanıyorum ve jQuery için bu bir seçenek değil çünkü projem buna bağlı olan SignalR kullanıyor. Artık javascript ES6 tarafından kullanılan sınıflar söz konusu olduğunda, verilere bellekte depolanma şeklini kapsayan işlev olan özelliklere erişilir. Inşaatçılar için, fabrikaları kullanarak uygun bir yolu vardır.
Anthony Brenelière

OP açıkça REST için basit veri modelleri hakkında. Gereksiz derecede karmaşık hale getiriyorsunuz çocuklar. Ve evet, Jquery'yi ek şeyler için kullanabilirsiniz, ancak% 1'ini kullanmak için büyük bir kütüphane içe aktarıyorsunuz. Şimdiye kadar gördüğüm bir kod kokusu.
Davor

18

Sunucudan aldığınız JSON nesnesinin dizginin arabirim özelliklerinin beklenen (okumaya uygun olduğunu) otomatik olarak kontrol etmek için henüz bir şey yoktur. Ancak Kullanıcı Tanımlı Tip Korumaları kullanabilirsiniz

Aşağıdaki arayüz ve aptal bir json nesnesi göz önüne alındığında (herhangi bir tür olabilir):

interface MyInterface {
    key: string;
 }

const json: object = { "key": "value" }

Üç olası yol:

Değişkenden sonra yerleştirilen Tür Onayı veya basit statik döküm

const myObject: MyInterface = json as MyInterface;

Değişken önce ve elmaslar arasında basit statik döküm

const myObject: MyInterface = <MyInterface>json;

C. Gelişmiş dinamik döküm, nesnenin yapısını kendiniz kontrol edersiniz

function isMyInterface(json: any): json is MyInterface {
    // silly condition to consider json as conform for MyInterface
    return typeof json.key === "string";
}

if (isMyInterface(json)) {
    console.log(json.key)
}
else {
        throw new Error(`Expected MyInterface, got '${json}'.`);
}

Sen olabilir burada bu örnek ile oynamak

Buradaki zorluğun isMyInterfaceişlevi yazmak olduğunu unutmayın . Umarım TS er ya da geç bir dekoratörü çalışma zamanına karmaşık yazmayı dışa aktarmak ve gerektiğinde çalışma zamanının nesnenin yapısını kontrol etmesini sağlar. Şimdilik, amacı hemen hemen aynı olan bir json şema doğrulayıcısı kullanabilirsiniz VEYA bu çalışma zamanı tipi kontrol işlevi oluşturucusu


1
Cevabınız üstte olmalı
afzalex

Kesinlikle. Bu doğrudan ts web sitesine dayanan en iyi cevaptır.
Burak Karakuş

15

Benim durumumda çalışıyor. Object.assign (hedef, kaynaklar ...) işlevlerini kullandım . İlk olarak, doğru nesnenin oluşturulması, daha sonra verileri json nesnesinden hedefe kopyalar.

let u:User = new User();
Object.assign(u , jsonUsers);

Ve daha gelişmiş bir kullanım örneği. Diziyi kullanan bir örnek.

this.someService.getUsers().then((users: User[]) => {
  this.users = [];
  for (let i in users) {
    let u:User = new User();
    Object.assign(u , users[i]);
    this.users[i] = u;
    console.log("user:" + this.users[i].id);
    console.log("user id from function(test it work) :" + this.users[i].getId());
  }

});

export class User {
  id:number;
  name:string;
  fullname:string;
  email:string;

  public getId(){
    return this.id;
  }
}

Özel bir mülkünüz olduğunda ne olur?
prasanthv

Çünkü jsonUser nesnesi bir Kullanıcı sınıfı değildir. İşlem olmadan Object.assign (u, jsonUsers); GetId () işlevini kullanamazsınız. Yalnızca atamadan sonra getId () işlevini kullanabileceğiniz geçerli bir User nesnesi alırsınız. GetId () işlevi yalnızca işlemin başarılı olduğu örnek içindir.
Adam111p

temp var atlayabilirsiniz - sadece yapthis.users[i] = new User(); Object.assign(this.users[i], users[i])
cyptus

ya da daha iyisi dönüş değerini kullanın:this.users[i] = Object.assign(new User(), users[i]);
cyptus

Bu uzun versiyon sadece açıklama amaçlıdır. Kodu istediğiniz kadar kısaltabilirsiniz :)
Adam111p

6

Kendi başına döküm olmasa da; Https://github.com/JohnWhiteTB/TypedJSON'u faydalı bir alternatif olarak buldum .

@JsonObject
class Person {
    @JsonMember
    firstName: string;

    @JsonMember
    lastName: string;

    public getFullname() {
        return this.firstName + " " + this.lastName;
    }
}
var person = TypedJSON.parse('{ "firstName": "John", "lastName": "Doe" }', Person);

person instanceof Person; // true
person.getFullname(); // "John Doe"

1
Döküm yapmıyor, gerçekten ne yapıyor?
DanielM

1
Bu çözüm çok fazla ek açıklama gerektiriyor. Gerçekten daha kolay bir yol yok mu?
JPNotADragon

3

interfaceType ( SomeType) öğenizden birini oluşturabilir ve nesneyi buna atabilirsiniz .

const typedObject: SomeType = <SomeType> responseObject;

3

Json nesnenizi bir typescript sınıfına yayınlamanız ve örnek yöntemlerini Object.setPrototypeOf, aşağıdaki kod snippet'inde yaptığım gibi kullanmanız gereken ortaya çıkan nesnede kullanabilmeniz gerekiyorsa :

Object.setPrototypeOf(jsonObject, YourTypescriptClass.prototype)

2

Çoğunlukla doğru fakat çok etkili olmayan cevapları olan eski bir soru. Ben bunu teklif ediyorum:

İnit () yöntemi ve statik döküm yöntemleri (tek bir nesne ve dizi için) içeren bir temel sınıf oluşturun . Statik yöntemler herhangi bir yerde olabilir; temel sınıf ve init () içeren sürüm daha sonra kolay uzantılara izin verir.

export class ContentItem {
    // parameters: doc - plain JS object, proto - class we want to cast to (subclass of ContentItem)
    static castAs<T extends ContentItem>(doc: T, proto: typeof ContentItem): T {
        // if we already have the correct class skip the cast
        if (doc instanceof proto) { return doc; }
        // create a new object (create), and copy over all properties (assign)
        const d: T = Object.create(proto.prototype);
        Object.assign(d, doc);
        // reason to extend the base class - we want to be able to call init() after cast
        d.init(); 
        return d;
    }
    // another method casts an array
    static castAllAs<T extends ContentItem>(docs: T[], proto: typeof ContentItem): T[] {
        return docs.map(d => ContentItem.castAs(d, proto));
    }
    init() { }
}

Benzer mekanik ( atama () ile ) @ Adam111p yazısında belirtilmiştir. Bunu yapmanın başka (daha eksiksiz) bir yolu. @Timothy Perez, ata () işlevini eleştirir , ancak burada tamamen uygundur.

Türetilmiş (gerçek) bir sınıf uygulayın:

import { ContentItem } from './content-item';

export class SubjectArea extends ContentItem {
    id: number;
    title: string;
    areas: SubjectArea[]; // contains embedded objects
    depth: number;

    // method will be unavailable unless we use cast
    lead(): string {
        return '. '.repeat(this.depth);
    }

    // in case we have embedded objects, call cast on them here
    init() {
        if (this.areas) {
            this.areas = ContentItem.castAllAs(this.areas, SubjectArea);
        }
    }
}

Şimdi hizmetten alınan bir nesneyi atabiliriz:

const area = ContentItem.castAs<SubjectArea>(docFromREST, SubjectArea);

Tüm SubjectArea nesneleri hiyerarşisi doğru sınıfa sahip olacaktır.

Bir kullanım örneği / örneği; Açısal bir hizmet oluşturun (yine soyut temel sınıf):

export abstract class BaseService<T extends ContentItem> {
  BASE_URL = 'http://host:port/';
  protected abstract http: Http;
  abstract path: string;
  abstract subClass: typeof ContentItem;

  cast(source: T): T {
    return ContentItem.castAs(source, this.subClass);
  }
  castAll(source: T[]): T[] {
    return ContentItem.castAllAs(source, this.subClass);
  }

  constructor() { }

  get(): Promise<T[]> {
    const value = this.http.get(`${this.BASE_URL}${this.path}`)
      .toPromise()
      .then(response => {
        const items: T[] = this.castAll(response.json());
        return items;
      });
    return value;
  }
}

Kullanımı çok basit hale gelir; Alan hizmeti oluşturma:

@Injectable()
export class SubjectAreaService extends BaseService<SubjectArea> {
  path = 'area';
  subClass = SubjectArea;

  constructor(protected http: Http) { super(); }
}

hizmetin get () yöntemi, SubjectArea nesneleri (tüm hiyerarşi) olarak zaten yayınlanmış bir dizinin Sözünü döndürür

Şimdi söyle, başka bir sınıfımız var:

export class OtherItem extends ContentItem {...}

Verileri alan ve doğru sınıfa atan bir hizmet oluşturmak şu kadar basittir:

@Injectable()
export class OtherItemService extends BaseService<OtherItem> {
  path = 'other';
  subClass = OtherItem;

  constructor(protected http: Http) { super(); }
}

2

Bir arabirimden genişletilmiş bir sınıf kullanın.

Sonra:

Object.assign(
                new ToWhat(),
                what
              )

Ve en iyisi:

Object.assign(
                    new ToWhat(),
                    <IDataInterface>what
                  )

Kime DataInterface denetleyicisi olur.



0

Enfes TS'de şöyle yapabilirsiniz:

const isMyInterface = (val: any): val is MyInterface => {
  if (!val) { return false; }
  if (!val.myProp) { return false; }
  return true;
};

Ve böyle kullanıcı daha:

if (isMyInterface(data)) {
 // now data will be type of MyInterface
}

0

Benzer bir ihtiyaca rastladım. Bana / REST api çağrısından gelen / belirli sınıf tanımı gelen JSON kolay dönüşüm verecek bir şey istedim. Bulduğum çözümler, sınıfımın kodunu yeniden yazmak ve ek açıklamalar veya benzerleri eklemek için yetersiz veya amaçtı.

Java gibi GSON sınıfları / JSON nesnelerine sınıflarını serileştirmek için kullanılan gibi bir şey istedim.

Daha sonra bir ihtiyaç ile birlikte, dönüştürücü JS'de de çalışacak, kendi paketimi yazmayı bitirdim.

Yine de, biraz yükü var. Ancak başladığında ekleme ve düzenleme için çok uygundur.

Modülü şununla başlatırsınız:

  1. dönüşüm şeması - alanlar arasında eşleştirmeye ve dönüşümün nasıl yapılacağını belirlemeye izin verme
  2. Sınıflar harita dizisi
  3. Dönüşüm işlevleri haritası - özel dönüşümler için.

Daha sonra kodunuzda, başlatılmış modülü aşağıdaki gibi kullanırsınız:

const convertedNewClassesArray : MyClass[] = this.converter.convert<MyClass>(jsonObjArray, 'MyClass');

const convertedNewClass : MyClass = this.converter.convertOneObject<MyClass>(jsonObj, 'MyClass');

veya JSON'a:

const jsonObject = this.converter.convertToJson(myClassInstance);

Npm paketine bu bağlantıyı ve ayrıca modülle nasıl çalışılacağına dair ayrıntılı bir açıklama kullanın: json-class-converter

Ayrıca için sarılır
: açısal kullanım açısal json sınıf-dönüştürücü


0

Nesneyi sınıf yapıcısına olduğu gibi iletin; Sözleşme veya kontrol yok

interface iPerson {
   name: string;
   age: number;
}

class Person {
   constructor(private person: iPerson) { }

   toString(): string {
      return this.person.name + ' is ' + this.person.age;
   }  
}


// runs this as // 
const object1 = { name: 'Watson1', age: 64 };
const object2 = { name: 'Watson2' };            // age is missing

const person1 = new Person(object1);
const person2 = new Person(object2 as iPerson); // now matches constructor

console.log(person1.toString())  // Watson1 is 64
console.log(person2.toString())  // Watson2 is undefined

0

Bu npm paketini kullanabilirsiniz. https://www.npmjs.com/package/class-converter

Kullanımı kolaydır, örneğin:

class UserModel {
  @property('i')
  id: number;

  @property('n')
  name: string;
}

const userRaw = {
  i: 1234,
  n: 'name',
};

// use toClass to convert plain object to class
const userModel = toClass(userRaw, UserModel);
// you will get a class, just like below one
// const userModel = {
//   id: 1234,
//   name: 'name',
// }

0

Şahsen ben bu tür bir son nokta tanımının alınan nesnenin türünü belirtmesine izin vermediğini korkunç buluyorum. Görünüşe göre bu gerçekten böyle, diğer dillerle yaptığım şeyi yapacağım ve JSON nesnesini sınıf tanımından ayıracağım ve sınıf tanımının JSON nesnesini tek veri üyesi olarak kullanması .

Boilerplate kodunu hor görüyorum, bu yüzden benim için genellikle türü korurken kodun en az miktarı ile istenen sonuca ulaşma meselesidir.

Aşağıdaki JSON nesne yapısı tanımlarını göz önünde bulundurun - bunlar bir son noktada alacağınız şey olacaktır, bunlar sadece yapı tanımlarıdır, yöntem yoktur.

interface IAddress {
    street: string;
    city: string;
    state: string;
    zip: string;
}

interface IPerson {
    name: string;
    address: IAddress;
}

Yukarıdakileri nesne yönelimli terimlerle düşünürsek, yukarıdaki arayüzler sınıf değildir, çünkü sadece bir veri yapısı tanımlarlar. OO terimlerindeki bir sınıf, verileri ve üzerinde çalışan kodu tanımlar.

Şimdi verileri ve üzerinde çalışan kodu belirten bir sınıf tanımladık ...

class Person {
    person: IPerson;

    constructor(person: IPerson) {
        this.person = person;
    }

    // accessors
    getName(): string {
        return person.name;
    }

    getAddress(): IAddress {
        return person.address;
    }

    // You could write a generic getter for any value in person, 
    // no matter how deep, by accepting a variable number of string params

    // methods
    distanceFrom(address: IAddress): float {
        // Calculate distance from the passed address to this persons IAddress
        return 0.0;
    }
}

Ve şimdi sadece IPerson yapısına uygun herhangi bir nesneyi aktarabilir ve yolumuza devam edebiliriz ...

   Person person = new Person({
            name: "persons name",
            address: {
                street: "A street address",
                city: "a city",
                state: "a state",
                zip: "A zipcode"
            }
        });

Aynı şekilde, son noktanızda alınan nesneyi, çizgileri boyunca bir şeyle işleyebiliriz ...

Person person = new Person(req.body);    // As in an object received via a POST call

person.distanceFrom({ street: "Some street address", etc.});

Bu çok daha performanslıdır ve verilerin kopyalanması belleğinin yarısını kullanır, her varlık türü için yazmanız gereken demirbaş kod miktarını önemli ölçüde azaltır. Sadece TypeScript tarafından sağlanan tip güvenliğine dayanır.



-1

Bu basit ve gerçekten iyi bir seçenek

let person = "{"name":"Sam","Age":"30"}";

const jsonParse: ((key: string, value: any) => any) | undefined = undefined;
let objectConverted = JSON.parse(textValue, jsonParse);

Ve sonra sahip olacaksın

objectConverted.name

-1

Bu kütüphaneyi burada kullandım: https://github.com/pleerock/class-transformer

<script lang="ts">
    import { plainToClass } from 'class-transformer';
</script>

Uygulama:

private async getClassTypeValue() {
  const value = await plainToClass(ProductNewsItem, JSON.parse(response.data));
}

Bazen, JSON biçimli bir veri olduğunu anlamak için plainToClass için JSON değerlerini ayrıştırmanız gerekir.


'Sınıf transformatörü' kitaplığı, yukarıdaki diğer yanıtta zaten önerilmiştir stackoverflow.com/a/40042282/52277
Michael Freidgeim

-1

Java Nesneleri döndüren ön uç Angular 6 ve arka uç Spring Spring uygulama kullanıyorum. Tek yapmam gereken, eşleşen özelliklere sahip açısal uygulamada benzer bir sınıf tanımlamak ve daha sonra 'açısal sınıf nesnesi' nesnesini ( aşağıdaki örnekte Şirket olarak comp ) kabul edebilirim.

Örneğin, aşağıdaki kullanıcı arabirim koduna bakın. Bir şeyin daha fazla netliğe ihtiyacı varsa yorumlarda bana bildirin.

  createCompany() {
    let company = new Company();
    company.name = this.companyName;

    this.companyService.createCompany(company).subscribe(comp => {
       if (comp !== null) {
        this.employerAdminCompany = comp as Company;
      }
    });
  }

burada şirket bahar çizme uygulamasında bir varlık nesnesi ve aynı zamanda Angular bir sınıftır.

export class Company {
    public id: number;
    public name: string;
    public owner: User;
    public locations: Array<Location>;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.