@@ -209,7 +209,7 @@ protected function toAttributes(Request $request): array
209209```
210210
211211#### Described attributes
212- _ ** @see ** [ described notation] ( ## described-notation ) _
212+ _ ** @see ** [ described notation] ( #described-notation ) _
213213
214214``` php
215215protected function toAttributes(Request $request): array
@@ -283,7 +283,7 @@ protected function toRelationships(Request $request): array
283283```
284284
285285#### Described attributes
286- _ ** @see ** [ described notation] ( ## described-notation ) _
286+ _ ** @see ** [ described notation] ( #described-notation ) _
287287
288288``` php
289289protected function toRelationships(Request $request): array
@@ -391,17 +391,18 @@ UserResource::collection(User::all()); // => JsonApiCollection
391391## Described notation
392392
393393### Value methods
394- | Method | Description |
395- | -----------| ------------------------------------------|
396- | ` bool ` | Cast to boolean |
397- | ` integer ` | Cast to integer |
398- | ` float ` | Cast to float |
399- | ` string ` | Cast to string |
400- | ` date ` | Cast to date, allow to use custom format |
401- | ` array ` | Cast to array |
402- | ` mixed ` | Don't cast, return as is |
403- | ` enum ` | Get enum value |
404- | ` struct ` | Custom struct. Accept an array of values |
394+ | Method | Description |
395+ | -----------| -----------------------------------------------------------------|
396+ | ` bool ` | Cast to boolean |
397+ | ` integer ` | Cast to integer |
398+ | ` float ` | Cast to float |
399+ | ` string ` | Cast to string |
400+ | ` date ` | Cast to date, allow to use custom format |
401+ | ` array ` | Cast to array, supports typed arrays with ` ->of() ` |
402+ | ` arrayOf ` | Helper method for typed arrays (alternative to ` array()->of() ` ) |
403+ | ` mixed ` | Don't cast, return as is |
404+ | ` enum ` | Get enum value |
405+ | ` struct ` | Custom struct. Accept an array of values |
405406
406407### Relation methods
407408| Method | Description |
@@ -454,3 +455,162 @@ Will return:
454455 "role": "ADMIN"
455456]
456457```
458+
459+ ### Typed Arrays
460+
461+ The ` array ` descriptor supports typed arrays to ensure all elements are cast to a specific type. This is useful when you need to guarantee type consistency across array elements.
462+
463+ #### Basic Usage
464+
465+ ``` php
466+ // UserResource.php
467+ protected function toAttributes(Request $request): array
468+ {
469+ return [
470+ // Array of strings - all values will be cast to string
471+ 'tags' => $this->array('tags')->of($this->string()),
472+
473+ // Array of integers - all values will be cast to integer
474+ 'scores' => $this->array('scores')->of($this->integer()),
475+
476+ // Array of floats
477+ 'prices' => $this->array('prices')->of($this->float()),
478+
479+ // Array of booleans
480+ 'flags' => $this->array('flags')->of($this->bool()),
481+ ];
482+ }
483+ ```
484+
485+ #### Using Class References
486+
487+ You can also use class references instead of descriptor instances:
488+
489+ ``` php
490+ use Ark4ne\JsonApi\Descriptors\Values\ValueString;
491+ use Ark4ne\JsonApi\Descriptors\Values\ValueInteger;
492+
493+ protected function toAttributes(Request $request): array
494+ {
495+ return [
496+ 'tags' => $this->array('tags')->of(ValueString::class),
497+ 'scores' => $this->array('scores')->of(ValueInteger::class),
498+ ];
499+ }
500+ ```
501+
502+ #### Alternative Syntax
503+
504+ You can also use the ` arrayOf() ` helper method:
505+
506+ ``` php
507+ protected function toAttributes(Request $request): array
508+ {
509+ return [
510+ 'tags' => $this->arrayOf($this->string(), 'tags'),
511+ 'scores' => $this->arrayOf($this->integer(), 'scores'),
512+ ];
513+ }
514+ ```
515+
516+ #### Nested Typed Arrays
517+
518+ For multi-dimensional arrays, you can nest ` array()->of() ` calls:
519+
520+ ``` php
521+ protected function toAttributes(Request $request): array
522+ {
523+ return [
524+ // 2D array (matrix) of integers
525+ 'matrix' => $this->array('matrix')->of(
526+ $this->array()->of($this->integer())
527+ ),
528+ ];
529+ }
530+ ```
531+
532+ #### With Closures and Transformations
533+
534+ Combine typed arrays with closures for data transformation:
535+
536+ ``` php
537+ protected function toAttributes(Request $request): array
538+ {
539+ return [
540+ // Transform and type cast
541+ 'doubled' => $this->array(fn() => array_map(fn($n) => $n * 2, $this->numbers))
542+ ->of($this->integer()),
543+
544+ // Access nested properties
545+ 'user_ids' => $this->array(fn() => $this->users->pluck('id'))
546+ ->of($this->integer()),
547+ ];
548+ }
549+ ```
550+
551+ #### With Conditions
552+
553+ Typed arrays support all conditional methods:
554+
555+ ``` php
556+ protected function toAttributes(Request $request): array
557+ {
558+ return [
559+ // Only include if not null
560+ 'tags' => $this->array('tags')->of($this->string())->whenNotNull(),
561+
562+ // Only include if array is not empty
563+ 'scores' => $this->array('scores')->of($this->integer())->whenFilled(),
564+
565+ // Conditional based on closure
566+ 'admin_notes' => $this->array('notes')->of($this->string())
567+ ->when(fn() => $request->user()->isAdmin()),
568+ ];
569+ }
570+ ```
571+
572+ > ** ⚠️ Important Note:** Conditions applied to the item type (inside ` of() ` ) are ** not evaluated per-item** . They apply to the entire array descriptor, not individual elements.
573+ >
574+ > ``` php
575+ > // ❌ This will NOT filter individual items
576+ > 'even-numbers' => $this->array('numbers')->of(
577+ > $this->integer()->when(fn($request, $model, $attr) => $attr % 2 === 0)
578+ > )
579+ > // All items will be included, the when() doesn't filter per item
580+ >
581+ > // ✅ To filter items, do it before passing to the array
582+ > 'even-numbers' => $this->array(
583+ > fn() => array_filter($this->numbers, fn($n) => $n % 2 === 0)
584+ > )->of($this->integer())
585+ > ```
586+
587+ #### Example
588+
589+ Given a model with mixed-type arrays:
590+
591+ ```php
592+ $user = new User([
593+ 'tags' => ['php', 'laravel', 123, true],
594+ 'scores' => [95.5, '87', 92, '78.9'],
595+ ]);
596+ ```
597+
598+ The resource will ensure type consistency:
599+
600+ ``` php
601+ protected function toAttributes(Request $request): array
602+ {
603+ return [
604+ 'tags' => $this->array('tags')->of($this->string()),
605+ 'scores' => $this->array('scores')->of($this->integer()),
606+ ];
607+ }
608+ ```
609+
610+ Output:
611+ ``` json
612+ {
613+ "tags" : [" php" , " laravel" , " 123" , " 1" ],
614+ "scores" : [95 , 87 , 92 , 78 ]
615+ }
616+ ```
0 commit comments