node.js - Nest.js - DTO doğrulama ve string'i tarihe dönüştürme
Gelecek isteğin ISO 8601 standart zaman damgası olmasını bekliyorum, örneğin "2023-12-04T15:30:00Z" gibi (doğal olarak JSON içinde bir string olarak geliyor, ben de bunu JavaScript Date'e dönüştürmeye çalışıyorum)
İşte benim DTO sınıfım:
export class CreateBookingDto implements ICreateBookingDto {
@ApiProperty()
@IsISO8601({ strict: true, strictSeparator: true })
@Transform(() => Date)
@IsNotEmpty()
from_date: Date;
@ApiProperty()
@IsISO8601({ strict: true })
@IsNotEmpty()
@Type(() => Date)
to_date: Date;
}
Bir istek göndermeye çalıştığımda, bu Bad Request Exception mesajını alıyorum: "from_date geçerli bir ISO 8601 tarih dizisi olmalıdır" (to_date için de aynı)
istek:
{
"from_date": "2023-12-04T15:30:00Z",
"to_date": "2023-12-04T16:30:00Z"
}
Bunu da denedim:
@Type(({ value }) => new Date(value))
to_date: Date;
ama hâlâ aynı sorun
Ama böyle değiştirdiğimde:
from_date: any;
// to_date also
İsteği kabul ediyor, çalışması için bunu string'e çevirebilirim, ama ben Tarih istiyorum.
Yani, benim sorularım şunlar:
- Gelecek "from_date" ve "to_date" değerlerini doğru şekilde Date türüne nasıl dönüştürebilirim?
- Onları herhangi birine ayarladığımda bile, "2023-12-04" gibi tarihleri kabul ediyor, ben sadece timestampz bekliyorum, doğru yol nedir?
Cevap #1
Dönüşümler, doğrulamadan önce gerçekleşir, çünkü class-validator'ın çalışabilmesi için bir sınıf örneğine ihtiyacı vardır ve body-parser yalnızca JSON/form-urlencoded gövdesini serileştirmeden çıkarır, ancak bunun bir sınıfını oluşturmaz (çünkü JS zorunlu olarak sınıf tabanlı bir dil değildir). Bu nedenle Nest, ValidationPipe içinde class-transformer'ı kullanarak class-validator'ın daha sonra DTO ve dekoratörlerden alınan meta verileri kullanarak doğrulama yapacağı sınıf örneğini oluşturur. İşte bu yüzden sizin @IsISO8601() dekoratörünüz başarısız oluyor, çünkü o zaten bir Date örneği; bunun yerine @IsDate() kullanmalısınız. Eğer stringi bir Date'e dönüştürmeden önce bazı doğrulamalar yapmak istiyorsanız, class-transformer dokümanlarındaki gelişmiş yaklaşımla @Transform() dekoratörünü kullanabilirsiniz ve şöyle bir şey yapabilirsiniz
export class CreateBookingDto implements ICreateBookingDto {
@ApiProperty()
@IsISO8601({ strict: true, strictSeparator: true })
@Transform(({ value }) => {
const isValidDate = isISO8601(value, { strict: true, strictSeparator: true });
if (!isValidDate) {
throw new Error(`Property "from_date" should be a valid ISO8601 date string`);
}
return new Date(value);
})
@IsNotEmpty()
from_date: Date;
@ApiProperty()
@IsISO8601({ strict: true })
@IsNotEmpty()
@Type(() => Date)
to_date: Date;
}
Zorunlu olarak güzel değil, ama işe yarıyor ve bunu kendi değişkeninize kaydedebilir ve dekoratörü tekrar kullanılabilir hale getirebilirsiniz.
