@@ -469,6 +469,9 @@ public function getFilters(): array
469469 }
470470 return $ this ->toUpperSnakeCase ($ value );
471471 }),
472+ new TwigFilter ('propertyAssignment ' , function (array $ property , array $ spec ) {
473+ return $ this ->getPropertyAssignment ($ property , $ spec );
474+ }),
472475 ];
473476 }
474477
@@ -518,6 +521,9 @@ protected function getPropertyType(array $property, array $spec, string $generic
518521 if ($ property ['type ' ] === 'array ' ) {
519522 $ type = 'List< ' . $ type . '> ' ;
520523 }
524+ } elseif (isset ($ property ['enum ' ])) {
525+ $ enumName = $ property ['enumName ' ] ?? $ property ['name ' ];
526+ $ type = \ucfirst ($ enumName );
521527 } else {
522528 $ type = $ this ->getTypeName ($ property );
523529 }
@@ -551,4 +557,71 @@ protected function hasGenericType(?string $model, array $spec): string
551557
552558 return false ;
553559 }
560+
561+ /**
562+ * Generate property assignment logic for model deserialization
563+ *
564+ * @param array $property
565+ * @param array $spec
566+ * @return string
567+ */
568+ protected function getPropertyAssignment (array $ property , array $ spec ): string
569+ {
570+ $ propertyName = $ property ['name ' ];
571+ $ escapedPropertyName = str_replace ('$ ' , '\$ ' , $ propertyName );
572+ $ mapKey = "map[ \"$ escapedPropertyName \"] " ;
573+
574+ // Handle sub-schema (nested objects)
575+ if (isset ($ property ['sub_schema ' ]) && !empty ($ property ['sub_schema ' ])) {
576+ $ subSchemaClass = $ this ->toPascalCase ($ property ['sub_schema ' ]);
577+ $ hasGenericType = $ this ->hasGenericType ($ property ['sub_schema ' ], $ spec );
578+ $ nestedTypeParam = $ hasGenericType ? ', nestedType ' : '' ;
579+
580+ if ($ property ['type ' ] === 'array ' ) {
581+ return "( $ mapKey as List<Map<String, Any>>).map { " .
582+ "$ subSchemaClass.from(map = it $ nestedTypeParam) } " ;
583+ } else {
584+ return "$ subSchemaClass.from( " .
585+ "map = $ mapKey as Map<String, Any> $ nestedTypeParam " .
586+ ") " ;
587+ }
588+ }
589+
590+ // Handle enum properties
591+ if (isset ($ property ['enum ' ]) && !empty ($ property ['enum ' ])) {
592+ $ enumName = $ property ['enumName ' ] ?? $ property ['name ' ];
593+ $ enumClass = $ this ->toPascalCase ($ enumName );
594+ $ nullCheck = $ property ['required ' ] ? '!! ' : ' ?: null ' ;
595+
596+ if ($ property ['required ' ]) {
597+ return "$ enumClass.values().find { " .
598+ "it.value == $ mapKey as String " .
599+ "} $ nullCheck " ;
600+ }
601+
602+ return "$ enumClass.values().find { " .
603+ "it.value == ( $ mapKey as? String) " .
604+ "} $ nullCheck " ;
605+ }
606+
607+ // Handle primitive types
608+ $ nullableModifier = $ property ['required ' ] ? '' : '? ' ;
609+
610+ if ($ property ['type ' ] === 'integer ' ) {
611+ return "( $ mapKey as $ nullableModifier Number) " .
612+ ($ nullableModifier ? '? ' : '' ) . '.toLong() ' ;
613+ }
614+
615+ if ($ property ['type ' ] === 'number ' ) {
616+ return "( $ mapKey as $ nullableModifier Number) " .
617+ ($ nullableModifier ? '? ' : '' ) . '.toDouble() ' ;
618+ }
619+
620+ // Handle other types (string, boolean, etc.)
621+ $ kotlinType = $ this ->getPropertyType ($ property , $ spec );
622+ // Remove nullable modifier from type since we handle it in the cast
623+ $ kotlinType = str_replace ('? ' , '' , $ kotlinType );
624+
625+ return "$ mapKey as $ nullableModifier $ kotlinType " ;
626+ }
554627}
0 commit comments