Angular 2 Дата десериализации
У меня есть приложение Angular 2. Служба запрашивает данные из api, которые возвращают результаты следующим образом:
{
"data":[
{"id":1,"timestamp":"2016-04-17T19:52:53.4510935+01:00","sourceDatabaseServer":"127.0.0.1","sourceDatabaseName":"Database1","targetDatabaseServer":"192.168.99.101","targetDatabaseName":"Database2"},
{"id":2,"timestamp":"2016-04-17T19:52:53.4510935+01:00","sourceDatabaseServer":"127.0.0.2","sourceDatabaseName":"Database3","targetDatabaseServer":"192.168.99.102","targetDatabaseName":"Database4"},
{"id":3,"timestamp":"2016-04-17T19:52:53.4510935+01:00","sourceDatabaseServer":"127.0.0.3","sourceDatabaseName":"Database5","targetDatabaseServer":"192.168.99.103","targetDatabaseName":"Database6"}
]
}
Моя служба Angular 2 выглядит так (я сократил обработку ошибок для краткости, поскольку мы находимся на счастливом пути здесь):
getList() : Observable<SomeModel[]> {
return this._http.get(this._getListUrl).map(this.extractData);
}
private extractData(res: Response) {
return res.json().data || {};
}
и мой компонент следующим образом:
results: SomeModel[];
errorMessage: string;
ngOnInit() {
this._someService.getList()
.subscribe(
results => this.results = results,
error => this.errorMessage = <any>error);
}
и моя модель:
export class SomeModel {
constructor(
public id: number,
public timestamp: Date,
public sourceDatabaseServer: string,
public sourceDatabaseName: string,
public targetDatabaseServer: string,
public targetDatabaseName: string
) { }
}
Все выглядело так, как будто оно работало, но когда я пытался отображать временную метку с помощью DatePipe, так что {{item.timestamp | date:'short'}}
приложение взорвалось со следующим сообщением об ошибке:
Invalid argument '2016-04-17T19:40:38.2424240+01:00' for pipe 'DatePipe' in [{{result.timestamp | date:'short'}}
После некоторого исследования я считаю, что временная метка фактически не преобразуется в тип Date
, а вместо этого устанавливается только string
. Я предполагаю, что это потому, что тип Date
не известен в то время, когда вызывается Response.json()
? или я вообще что-то пропустил? Есть ли для этого исправление или работа?
Ответы
Ответ 1
Я бы сопоставил поле строки с датой:
getList() : Observable<SomeModel[]> {
return this._http.get(this._getListUrl).map(this.extractData);
}
private extractData(res: Response) {
var data = res.json().data || [];
data.forEach((d) => {
d.timestamp = new Date(d.timestamp);
});
return data;
}
Ответ 2
В трубке date
принимаются значения date
не строковые значения.
Смотрите Как получить объект Date из json Response в typescript для того, как конвертировать даты в JSON.
В качестве альтернативы вы можете создать свой собственный строковый протокол преобразования
@Pipe({name: 'toDate'})
export class StringToDate implements PipeTransform {
transform(value, [exponent]) : number {
if(value) {
return new Date(value);
}
}
}
а затем используйте его как
{{item.timestamp |toDate | date:'short'}}
Подсказка: не забудьте добавить трубу в pipes: [StringToDate]
на декортере @Component(...)
, где вы хотите ее использовать.
См. также
Ответ 3
Попробуйте мой пример, если его работа для вас. И вот документы для Date и Pipe.
<span>Date : {{announcement.createdAt | date:'EEE, d MMM,y'}}</span>
<span>Time : {{announcement.createdAt | date:'shortTime'}}</span>
Выход:
Date : Tue, 20 Dec,2016
Time : 2:22 PM
Ответ 4
JSON не предоставляет спецификацию даты, поэтому полностью зависит от того, как она сериализована/десериализована.
Вы можете использовать reviver
параметр JSON.parse
:
this._http.get(this._getListUrl).map(res => JSON.parse(res.text(), this.reviver));
reviver(key, value):any
{
if('timestamp' === key){
//you can use any de-serialization algorithm here
return new Date(value);
}
return value;
}