Как преобразовать объект JSON в класс машинописи

394

Я прочитал объект JSON с удаленного сервера REST. Этот объект JSON имеет все свойства класса машинописного текста (в соответствии с дизайном). Как преобразовать полученный полученный объект JSON в тип var?

Я не хочу заполнять машинописный текст var (то есть иметь конструктор, который принимает этот объект JSON). Он большой, и копирование всего через подобъект по подобъекту и свойству по свойству займет много времени.

Обновление: однако вы можете привести его к интерфейсу машинописи!

Дэвид Тилен
источник
вы можете использовать github.com/vojtechhabarta/typescript-generator для генерации интерфейсов TypeScript в случае, если ваш JSON сопоставлен с использованием классов Java
Vojta
Я написал небольшую библиотеку для кастинга: sulphur-blog.azurewebsites.net/typescript-mini-cast-library
Камилла Винц
1
JSON объект = JavaScript объект нотации объекта. Там не хватает объектов, я говорю, что мы добавим еще пару для хорошей меры.
ошибка
1
Я сделал инструмент для этого beshanoe.github.io/json2ts
beshanoe
Создание прототипа класса TypeScript для определения вашего объекта не повредит реальному производственному коду. Посмотрите на скомпилированный файл JS, все определения будут удалены, так как они не являются частью JS.
FisNaN

Ответы:

167

Вы не можете просто преобразовать результат простого старого JavaScript из запроса Ajax в прототипный экземпляр класса JavaScript / TypeScript. Для этого существует ряд методов, которые обычно включают копирование данных. Если вы не создадите экземпляр класса, у него не будет никаких методов или свойств. Это останется простым объектом JavaScript.

Хотя, если бы вы имели дело только с данными, вы могли бы просто выполнить приведение к интерфейсу (поскольку это просто структура времени компиляции), для этого потребовалось бы использовать класс TypeScript, который использует экземпляр данных и выполняет операции с этими данными.

Некоторые примеры копирования данных:

  1. Копирование объекта AJAX JSON в существующий объект
  2. Разобрать строку JSON в прототип конкретного объекта в JavaScript

По сути, вы бы просто:

var d = new MyRichObject();
d.copyInto(jsonResult);
WiredPrairie
источник
Я согласен с вашим ответом. Кроме того, хотя сейчас я не в состоянии найти и протестировать его, я думаю, что эти два шага можно объединить, задав функцию пробуждения в качестве параметра для JSON.parse(). И то, и другое еще нужно сделать, но синтаксически их можно объединить.
А.А.Ольде
Конечно, это тоже может сработать - у меня нет ощущения, будет ли это более эффективным, хотя для каждого свойства потребуется вызывать дополнительный вызов функции.
WiredPrairie
Определенно не тот ответ, который я искал :( Из любопытства, почему это так? Мне кажется, как работает javascript, что это должно быть выполнимо.
Дэвид Тилен
Нет, это не работает в TypeScript, потому что в JavaScript нет простого способа сделать это.
WiredPrairie
1
Как насчетObject.setPrototypeOf
Петах
103

У меня была та же проблема, и я нашел библиотеку, которая выполняет эту работу: https://github.com/pleerock/class-transformer .

Это работает так:

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

Он поддерживает вложенные дочерние элементы, но вы должны украсить члена вашего класса.

Пак
источник
14
Эта блестящая небольшая библиотека решила ее идеально с минимальными усилиями ( @Typeхотя не забывайте свои аннотации). Этот ответ заслуживает большего доверия.
Бенни Боттема
Ого, эта библиотека не такая крошечная, она может иметь все, что вам нужно, даже позволяет вам контролировать преобразование с помощью декоратора @transform: D
Диего Фернандо Мурильо Валенси
3
Обратите внимание, что эта библиотека почти не поддерживается. Он больше не работает с Angular5 +, и, поскольку они больше не объединяют запросы на извлечение, я не думаю, что они будут работать над этим в ближайшее время. Это отличная библиотека.
Кентор
Есть обходной путь для Angular5 + (на самом деле это Angular Bug): github.com/typestack/class-transformer/issues/108
Пак,
2
Это отлично работает в Angular 6 (по крайней мере, для моего
варианта
54

В TypeScript вы можете сделать утверждение типа с помощью интерфейса и обобщенных типов, например, так:

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

Где ILocationMap описывает форму ваших данных. Преимущество этого метода в том, что ваш JSON может содержать больше свойств, но форма удовлетворяет условиям интерфейса.

Надеюсь, это поможет!

user756310
источник
49
К вашему сведению: это утверждение типа, а не актерский состав.
WiredPrairie
6
Смотрите здесь для различия между утверждением типа и приведением .
Стефан Ханке
7
Где я могу найти Utilities.JSONLoader?
HypeXR
22
Но у этого не будет никаких методов, как упомянуто в ответе.
Мартин Колл
1
@StefanHanke выглядит так, как будто URL-адрес немного изменился: «Утверждение типа против
чтения
37

Если вы используете ES6, попробуйте это:

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()
})

Но , к сожалению, этот способ не будет работать на объекте гнезда .

migcoder
источник
4
Они попросили это в Typescript.
joe.feser
HI @ joe.feser, я упоминаю ES6, потому что таким образом требуется метод 'Object.assign'.
Migcoder
1
Если конструктор по умолчанию отсутствует, целевой экземпляр может быть создан с помощью Object.create(MyClass.prototype)обхода конструктора вообще.
Марчелло
Подробнее об ограничении вложенных объектов см. В stackoverflow.com/questions/22885995/…
Майкл Фрейдгейм
28

Я нашел очень интересную статью о приведении JSON к классу Typescript:

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

Вы получите следующий код:

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: один лайнер

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

Подробный ответ

Я бы не стал рекомендовал подход Object.assign, поскольку он может ненадлежащим образом засорять ваш экземпляр класса нерелевантными свойствами (а также определенными замыканиями), которые не были объявлены внутри самого класса.

В классе, в который вы пытаетесь десериализоваться, я бы гарантировал, что все свойства, которые вы хотите десериализовать, определены (нуль, пустой массив и т. Д.). Определяя ваши свойства с начальными значениями, вы открываете их видимость при попытке перебрать членов класса для назначения значений (см. Метод десериализации ниже).

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];
      }
    }
  }
}

В приведенном выше примере я просто создал метод десериализации. В реальном примере я бы централизовал его в повторно используемом базовом классе или методе обслуживания.

Вот как использовать это в чем-то вроде http соответственно ...

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

Если tslint / ide жалуется на несовместимость типа аргумента, просто приведите аргумент к тому же типу, используя угловые скобки <YourClassName>, например:

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

Если у вас есть члены класса определенного типа (иначе: экземпляр другого класса), вы можете привести их к типизированным экземплярам с помощью методов getter / setter.

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));
  }
}

Приведенный выше пример десериализует как acct, так и список задач в их соответствующие экземпляры классов.

Тимоти Перес
источник
Я получаю это сообщение об ошибке: Тип «{имя: строка, возраст: номер, идентификатор: номер}» не может быть преобразован в тип «Персона». Свойство 'id' является закрытым в типе 'Person', но не в типе '{name: string, age: number, id: number}'
utiq
Как я должен использовать это с перечислениями? Должен ли я использовать подход конкретного типа и добавить для него методы получения и установки?
Тадия
@TimothyParez Когда вы ставите задачи?
Кей
Я пытался сделать что-то подобное, но мой массив задач пуст, когда я console.log человек.
Кей
Для этого мне нужно было добавить индексную подпись в класс: класс экспорта Person {[key: string]: any (...)}
Азимов
18

Предполагая, что json имеет те же свойства, что и ваш класс машинописи, вам не нужно копировать свойства Json в объект машинописи. Вам просто нужно создать свой объект Typescript, передавая данные json в конструктор.

В вашем обратном вызове ajax вы получаете компанию:

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

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

Для того, чтобы сделать эту работу:

1) Добавьте конструктор в свой класс Typescript, который принимает данные json в качестве параметра. В этом конструкторе вы расширяете свой объект json с помощью jQuery, например так:$.extend( this, jsonData) . $ .extend позволяет сохранить прототипы javascript при добавлении свойств объекта json.

2) Обратите внимание, что вам придется сделать то же самое для связанных объектов. В случае Employees в примере вы также создаете конструктор, принимающий часть данных json для сотрудников. Вы вызываете $ .map для перевода сотрудников json в машинописные объекты Employee.

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);
    }
}

Это лучшее решение, которое я нашел при работе с классами Typescript и объектами json.

Энтони Бренельер
источник
Я предпочитаю это решение над реализацией и обслуживанием интерфейсов, потому что мои приложения Angular2 имеют реальную модель приложения, которая может отличаться от модели веб-сервисов, которые использует мое приложение. Он может иметь частные данные и рассчитанные свойства.
Энтони Бренельер
7
Использование JQuery в проектах Angular - ужасная идея. И если ваши модели содержат множество функций, они больше не являются моделями.
Давор
1
@Davor Ты имеешь ввиду POJO или модель? POJO (в основном простые объекты) не имеют функций, в то время как модель является более широким термином и включает репозиторий. Шаблон репозитория, в отличие от POJO, связан с функциями, но все же является моделью.
Форсберг
@Davor: использование JQuery в проектах Angular не является плохой идеей, если вы не используете его для манипулирования DOM, что действительно ужасная идея. Я использую любую библиотеку, которая мне нужна для моих проектов Angular, и для jQuery это не вариант, потому что мой проект использует SignalR, который зависит от него. В случае классов, теперь используемых в javascript ES6, доступ к данным осуществляется через свойства, которые являются функцией, которая инкапсулирует способ хранения данных в памяти. Для конструкторов существует правильный способ использования фабрик.
Энтони Бренельер
ОП явно о простых моделях данных для REST. Вы делаете это слишком сложно, ребята. И да, вы можете использовать Jquery для дополнительных вещей, но вы импортируете огромную библиотеку, чтобы использовать 1% ее. Это кодовый запах, если я когда-либо видел.
Давор
18

Автоматически проверять, есть ли у объекта JSON, полученного с сервера, ожидаемые (читай, соответствуют) свойства интерфейса машинописного текста, пока нечем. Но вы можете использовать Определяемые пользователем Стражи Типа

Учитывая следующий интерфейс и глупый объект json (это мог быть любой тип):

interface MyInterface {
    key: string;
 }

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

Три возможных способа:

A. Утверждение типа или простое статическое приведение после переменной

const myObject: MyInterface = json as MyInterface;

B. Простое статическое приведение, перед переменной и между бриллиантами

const myObject: MyInterface = <MyInterface>json;

C. Продвинутый динамический состав, вы сами проверяете структуру объекта

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}'.`);
}

Вы можете поиграть с этим примером здесь

Обратите внимание, что здесь трудность заключается в написании isMyInterfaceфункции. Я надеюсь, что TS добавит декоратор рано или поздно, чтобы экспортировать сложную типизацию во время выполнения и позволить среде выполнения проверять структуру объекта при необходимости. На данный момент вы можете использовать валидатор схемы json, цель которого примерно такая же, ИЛИ этот генератор функций проверки типа во время выполнения.

Флавиен Волкен
источник
1
Ваш ответ должен быть наверху, я думаю
afzalex
Определенно. Это лучший ответ, который опирается непосредственно на веб-сайт TS.
Бурак Каракуш
15

В моем случае это работает. Я использовал функции Object.assign (цель, источники ...) . Сначала создается правильный объект, затем копируются данные из объекта json в цель. Пример:

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

И более продвинутый пример использования. Пример использования массива.

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;
  }
}
Adam111p
источник
Что происходит, когда у вас есть частная собственность?
prasanthv
Потому что объект jsonUser не является классом User. Без операции Object.assign (u, jsonUsers); Вы не можете использовать функцию getId (). Только после назначения вы получаете действительный объект User, в котором вы можете использовать функцию getId (). Функция getId () предназначена только для примера того, что операция прошла успешно.
Adam111p
Вы можете пропустить временную this.users[i] = new User(); Object.assign(this.users[i], users[i])
переменную
или даже лучше использовать возвращаемое значение:this.users[i] = Object.assign(new User(), users[i]);
cyptus
Эта длинная версия только для объяснения. Вы можете сократить код столько, сколько хотите :)
Adam111p
6

Пока это не кастинг как таковой; Я нашел https://github.com/JohnWhiteTB/TypedJSON полезной альтернативой.

@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
Это не кастинг, что он на самом деле делает?
DanielM
1
Это решение требует очень много аннотаций. Неужели нет более легкого пути?
JPNotADragon
3

Вы можете создать interfaceсвой тип ( SomeType) и привести объект в него.

const typedObject: SomeType = <SomeType> responseObject;
Джаянт Варшней
источник
3

Если вам нужно привести ваш объект json к классу машинописного текста и иметь методы экземпляра, доступные в результирующем объекте, который вам нужно использовать Object.setPrototypeOf, как я сделал в фрагменте кода ниже:

Object.setPrototypeOf(jsonObject, YourTypescriptClass.prototype)
s_bighead
источник
2

Старый вопрос с в основном правильными, но не очень эффективными ответами. Вот что я предлагаю:

Создайте базовый класс, который содержит метод init () и статические методы приведения (для одного объекта и массива). Статические методы могут быть где угодно; версия с базовым классом и init () впоследствии позволяет легко расширяться.

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() { }
}

Подобная механика (с assign () ) была упомянута в посте @ Adam111p. Просто еще один (более полный) способ сделать это. @Timothy Perez критически относится к assign () , но imho здесь вполне уместно.

Реализуйте производный (настоящий) класс:

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);
        }
    }
}

Теперь мы можем привести объект, полученный из сервиса:

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

Вся иерархия SubjectArea объектов будет иметь правильный класс.

Вариант использования / пример; создайте сервис Angular (снова абстрактный базовый класс):

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;
  }
}

Использование становится очень простым; создать сервис Area:

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

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

Метод get () сервиса вернет Promise для массива, уже приведенного как SubjectArea объектам (вся иерархия)

Теперь скажите, у нас есть другой класс:

export class OtherItem extends ContentItem {...}

Создание службы, которая извлекает данные и приводит к правильному классу, так же просто, как:

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

  constructor(protected http: Http) { super(); }
}
Нормунд Калнберзиньш
источник
2

Используйте класс, расширенный из интерфейса.

Затем:

Object.assign(
                new ToWhat(),
                what
              )

И лучше всего:

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

То, что становится контроллером DataInterface.

Сэм
источник
1

https://jvilk.com/MakeTypes/

Вы можете использовать этот сайт для создания прокси для вас. он генерирует класс и может анализировать и проверять ваш входной объект JSON.

Амир Мехраби
источник
0

В конце TS вы можете сделать так:

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

И чем пользователь, как это:

if (isMyInterface(data)) {
 // now data will be type of MyInterface
}
Jaroslav
источник
0

Я столкнулся с аналогичной необходимостью. Я хотел что-то, что даст мне простое преобразование из / в JSON, которое приходит от вызова API REST в / из определенного определения класса. Решения, которые я нашел, были недостаточными или предназначались для того, чтобы переписать код моих классов и добавить аннотации или подобное.

Я хотел, чтобы что-то вроде GSON использовалось в Java для сериализации / десериализации классов в / из объектов JSON.

В связи с более поздней необходимостью, что конвертер будет работать и в JS, я закончил писать свой собственный пакет.

Это имеет, хотя, немного накладных расходов. Но при запуске его очень удобно добавлять и редактировать.

Вы инициализируете модуль с помощью:

  1. схема преобразования - позволяет отображать между полями и определять, как будет выполняться преобразование
  2. Массив карты классов
  3. Карта функций преобразования - для специальных преобразований.

Затем в своем коде вы используете инициализированный модуль, например:

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

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

или в JSON:

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

Используйте эту ссылку на пакет npm, а также подробное объяснение того, как работать с модулем: json-class-converter

Также обернул это для
углового использования в: angular-json-class-converter

Doronm
источник
0

Передайте объект как есть конструктору класса; Нет соглашений или проверок

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

Вы можете использовать этот пакет npm. https://www.npmjs.com/package/class-converter

Он прост в использовании, например:

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',
// }
QC-гепарда
источник
0

Лично я нахожу это ужасным, что машинопись не позволяет определению конечной точки указывать тип получаемого объекта. Похоже, что это действительно так, я бы сделал то же, что и с другими языками, и это то, что я отделил бы объект JSON от определения класса, и чтобы определение класса использовало объект JSON в качестве единственного члена данных ,

Я презираю шаблонный код, поэтому для меня это обычно вопрос достижения желаемого результата с наименьшим количеством кода при сохранении типа.

Рассмотрим следующие определения структуры объекта JSON - это будет то, что вы получите в конечной точке, это только определения структуры, а не методы.

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

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

Если мы думаем о вышеизложенном в объектно-ориентированных терминах, вышеупомянутые интерфейсы не являются классами, потому что они определяют только структуру данных. Класс в терминах ОО определяет данные и код, который работает с ними.

Итак, теперь мы определяем класс, который определяет данные и код, который работает с ними ...

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;
    }
}

И теперь мы можем просто передать любой объект, соответствующий структуре IPerson, и быть в пути ...

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

Таким же образом мы можем теперь обработать объект, полученный в вашей конечной точке, чем-то вроде ...

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

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

Это намного более эффективно и использует половину памяти для копирования данных, при этом значительно сокращая объем стандартного кода, который вы должны написать для каждого типа сущности. Он просто полагается на безопасность типов, обеспечиваемую TypeScript.

Родни П. Барбати
источник
0

Используйте «как» объявление:

const data = JSON.parse(response.data) as MyClass;
Даниэль Вальдебенито
источник
Эта техника была упомянута в этом ответе за два года до этого и, как обсуждалось в другом месте, не добавляет никаких функций, которые могут быть объявлены MyClass.
Еретик Обезьяна
-1

Это простой и действительно хороший вариант

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

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

И тогда у вас будет

objectConverted.name
SamazoOo
источник
-1

Я использовал эту библиотеку здесь: https://github.com/pleerock/class-transformer

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

Реализация:

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

Иногда вам нужно будет проанализировать значения JSON для plainToClass, чтобы понять, что это данные в формате JSON

Mac Chibueze
источник
Библиотека «преобразователь классов» уже предложена в другом ответе выше. Stackoverflow.com/a/40042282/52277
Майкл Фрейдгейм
-1

Я использую Angular 6 в веб-интерфейсе и Spring Boot-приложение в бэкэнде, которое возвращает объекты Java. Все, что мне нужно сделать, это определить аналогичный класс в угловом приложении, у которого есть совпадающие свойства, и тогда я могу принять объект «как» объект углового класса ( comp as Company в следующем примере).

См. Код переднего конца ниже, например. Дайте мне знать в комментариях, если что-то нуждается в большей ясности.

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

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

где company - это объект-сущность в весеннем загрузочном приложении, а также класс в Angular.

export class Company {
    public id: number;
    public name: string;
    public owner: User;
    public locations: Array<Location>;
}
Маниш Парихар
источник