@@ -175,15 +175,33 @@ pub struct ListParams {
175175
176176** Notlar:**
177177- ` #[param(...)] ` attribute'u RustAPI'de yok
178- - Validation kuralları için ` validator ` crate kullan:
178+ - Validation kuralları için RustAPI'nin built-in validation sistemini kullan:
179179 ``` rust
180+ use rustapi_validate :: Validate ;
181+
180182 #[derive(Debug , Deserialize , Validate , Schema )]
181183 pub struct CreateTask {
182184 #[validate(length(min = 1, max = 200))]
183185 pub title : String ,
186+ #[validate(email)]
187+ pub email : String ,
188+ }
189+
190+ // Handler'da ValidatedJson kullan
191+ async fn create_task (
192+ Json (task ): ValidatedJson <CreateTask >
193+ ) -> Result <Json <Task >> {
194+ // Validation otomatik yapılır, hata varsa 400 döner
195+ Ok (Json (task . into_inner ()))
184196 }
185197 ```
186198
199+ ** RustAPI Validation Özellikleri:**
200+ - ` ValidatedJson<T> ` - Otomatik validation + JSON parsing
201+ - ` #[validate(...)] ` attribute'ları rustapi-validate'den gelir
202+ - Validation hataları otomatik olarak formatlanır
203+ - Built-in validators: length, email, range, url, regex, custom, vb.
204+
187205---
188206
189207### 5. ** Handler Macro Kullanımı**
@@ -291,6 +309,143 @@ async fn handler() -> Html<String> { // ✅ Concrete type
291309
292310---
293311
312+ ### 7. ** DateTime<Utc > Schema Sorunu**
313+
314+ ** Sorun:**
315+ ``` rust
316+ #[derive(Debug , Serialize , Schema )]
317+ pub struct BookmarkResponse {
318+ pub id : u64 ,
319+ pub created_at : DateTime <Utc >, // ❌ RustApiSchema implement etmiyor
320+ pub updated_at : DateTime <Utc >,
321+ }
322+ ```
323+ ```
324+ error[E0277]: the trait bound `DateTime<Utc>: RustApiSchema` is not satisfied
325+ ```
326+
327+ ** Çözüm:**
328+ DateTime'ı String olarak kullan ve RFC3339 formatında dönüştür:
329+
330+ ``` rust
331+ #[derive(Debug , Serialize , Schema )]
332+ pub struct BookmarkResponse {
333+ pub id : u64 ,
334+ pub created_at : String , // ✅ String kullan
335+ pub updated_at : String ,
336+ }
337+
338+ // From/Into implementasyonunda dönüştür:
339+ impl From <& Bookmark > for BookmarkResponse {
340+ fn from (b : & Bookmark ) -> Self {
341+ Self {
342+ id : b . id,
343+ created_at : b . created_at. to_rfc3339 (), // DateTime -> String
344+ updated_at : b . updated_at. to_rfc3339 (),
345+ }
346+ }
347+ }
348+ ```
349+
350+ ** Alternatif - Unix Timestamp:**
351+ ``` rust
352+ #[derive(Debug , Serialize , Schema )]
353+ pub struct BookmarkResponse {
354+ pub created_at : i64 , // Unix timestamp (seconds)
355+ }
356+
357+ impl From <& Bookmark > for BookmarkResponse {
358+ fn from (b : & Bookmark ) -> Self {
359+ Self {
360+ created_at : b . created_at. timestamp (),
361+ }
362+ }
363+ }
364+ ```
365+
366+ ** Neden?**
367+ - ` chrono::DateTime<Utc> ` RustAPI'nin Schema trait'ini implement etmez
368+ - OpenAPI spec'inde date-time'lar genellikle RFC3339 string formatındadır
369+ - Client tarafında parse etmek daha kolay (JavaScript, Python, etc.)
370+ - String representation timezone bilgisini de içerir
371+
372+ ** Best Practice:**
373+ - Response DTO'larda ` String ` kullan (RFC3339 format)
374+ - Internal model'lerde ` DateTime<Utc> ` kullan
375+ - Dönüşümü From/Into trait'leriyle yap
376+
377+ ---
378+
379+ ### 8. ** Generic Type'larda Schema Trait Bound**
380+
381+ ** Sorun:**
382+ ``` rust
383+ #[derive(Debug , Serialize , Schema )]
384+ pub struct PaginatedResponse <T > { // ❌ T için trait bound eksik
385+ pub items : Vec <T >,
386+ pub total : usize ,
387+ }
388+ ```
389+ ```
390+ error[E0277]: the trait bound `T: RustApiSchema` is not satisfied
391+ ```
392+
393+ ** Çözüm:**
394+ Generic type'a ` RustApiSchema ` trait bound ekle:
395+
396+ ``` rust
397+ #[derive(Debug , Serialize , Schema )]
398+ pub struct PaginatedResponse <T : rustapi_openapi :: schema :: RustApiSchema > { // ✅ Trait bound
399+ pub items : Vec <T >,
400+ pub total : usize ,
401+ pub page : u32 ,
402+ pub limit : u32 ,
403+ }
404+
405+ // Kullanım:
406+ async fn list_items () -> Json <PaginatedResponse <ItemResponse >> {
407+ // ItemResponse: Schema derive'ına sahip olmalı
408+ Json (PaginatedResponse {
409+ items : vec! [],
410+ total : 0 ,
411+ page : 1 ,
412+ limit : 20 ,
413+ })
414+ }
415+ ```
416+
417+ ** Alternatif - Type Alias:**
418+ ``` rust
419+ // Generic yerine concrete type'lar için type alias
420+ pub type BookmarkList = PaginatedResponse <BookmarkResponse >;
421+ pub type CategoryList = PaginatedResponse <CategoryResponse >;
422+
423+ async fn list_bookmarks () -> Json <BookmarkList > {
424+ // ...
425+ }
426+ ```
427+
428+ ** Neden?**
429+ - ` Vec<T> ` RustApiSchema implement eder, ancak ` T ` de RustApiSchema olmalı
430+ - Compiler, ` T ` 'nin hangi trait'leri implement ettiğini bilmeli
431+ - OpenAPI spec oluştururken concrete type bilgisi gerekli
432+
433+ ** Trait Bound Şablonu:**
434+ ``` rust
435+ // ✅ Tam trait path
436+ T : rustapi_openapi :: schema :: RustApiSchema
437+
438+ // ✅ Import ile kullanım
439+ use rustapi_openapi :: schema :: RustApiSchema ;
440+ T : RustApiSchema
441+
442+ // ✅ Prelude'dan
443+ use rustapi_rs :: prelude :: * ;
444+ T : RustApiSchema
445+ ```
446+
447+ ---
448+
294449## 📋 Checklist: Yeni Bir Handler Eklerken
295450
296451- [ ] Query params struct'ına ` Schema ` derive ekle
0 commit comments