Я начинаю использовать Angular7 и следую инструкциям по созданию приложения, получающего данные от веб-службы и помещающего результат в массив объектов.
Работает до тех пор, пока данные уже поступают в виде массива.
Он перестает работать, когда данные поступают в формате JSON.
Проблема в том, что все ответы, которые я нашел на форумах в Интернете, включают использование функции карты, и, когда я ее использую, после включения соответствующего файла определения (из rxjs/operators
), я всегда получаю ошибку
"groups.map не является функцией".
Другая проблема заключается в том, что я продолжаю находить решения для старых версий Angular, которые, очевидно, больше не работают.
Я работаю с Angular 7.2.11, надписью 3.2.4, rxjs 6.3.3 и webpack 4.29.0, а не с какой-либо из многочисленных предыдущих версий.
Проблема, с которой я сталкиваюсь, должна быть очень распространенной: получение данных с сервера REST в формате JSON (вложенные и типизированные) и помещение данных в структуры данных (классы), необходимые приложению для выполнения различных задач. .
Кто-то предложил отказаться от классов TrueScript и напрямую работать с объектом JSON, возвращаемым вызовом http.get
.
Если это действительно лучшая практика, я хотел бы знать, как обрабатывать объект JSON в примере, который я разместил.
Я попытался полностью упростить вызов http:
getGroups(): Observable<Group[]> {
this.http.get(this.groupsUrl)
.subscribe(data => {console.log(data);
});
}
И веб-консоль показывает мне правильно загруженный массив «groups» в groups.service.ts
.
Однако следующий шаг, который отображает массив в объекты приложения, не работает.
Это класс:
export class Group {
public dn: string;
public cn: string[];
public name: string[];
public member: string[];
constructor(args: {
dn: string,
cn: string[],
name: string[],
member: string[]
}) {
this.dn = args.dn
this.cn = args.cn;
this.name = args.name;
this.member = args.member;
}
}
Это услуга:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Group } from './group';
import { MessageService } from './message.service';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';
export class GroupService {
private groupsUrl = '../assets/groups.json';
groups: Group[];
constructor(
private http: HttpClient,
private messageService: MessageService) { }
getGroups(): Observable<Group[]> {
return this.http.get<Group[]>(this.groupsUrl).pipe(
map(groups => groups.map(groupJson => new Group(groupJson))));
}
}
Это компонент:
getGroups(): void {
this.groupService.getGroups()
.subscribe(groups => this.groups = groups)
}
Это файл json:
{
"groups": [
{
"dn": "CN=mycn,OU=Groups,OU=valiant,OU=Organizations,DC=rag,DC=net",
"cn": [
"mycn"
],
"name": [
"mycn"
],
"member": [
"changz",
"gorkony",
"martoks",
"azetburn"
]
},
...
]
}
Для тех, у кого такая же проблема, я выкладываю здесь решение, построенное с помощью пользователя Hari Prathap:
groups: Group[];
getConfig() {
return this.http.get(this.configUrl).pipe(
map(res => {
return {
errMessage: res.errmessage,
errCode: res.errcode,
groups: res.data.groups.map(obj => new Group(obj))
};
})
);
}
ngOnInit() {
this.getConfig().subscribe(ret => {
console.log("errCode", ret.errCode);
console.log("errMessage", ret.errMessage);
console.log("groups", ret.groups);
this.groups = ret.groups;
console.log("Group 1", this.groups[1]);
});
}
Ключом к решению проблемы было указание на тот факт, что возвращаемое значение функции http.get представляет весь ответ от сервера REST, а не интересующую меня часть групп.
Часть групп доступна через "." оператор, хотя ни IDE, ни компилятор не знают точную структуру JSON, читаемого во время компиляции.
Компилятор фактически выдает ОШИБКУ, но, тем не менее, код работает.
Группы, извлеченные таким образом из ответа, затем могут быть отображены в массив объектов, имеющих такую же структуру массива, что и в файле JSON.
Этой ошибки можно избежать, используя следующие обозначения:
groups: res["data"].groups.map(obj => new Group(obj))