@@ -78,6 +78,10 @@ public NimClientCodegen() {
7878 .excludeSchemaSupportFeatures (
7979 SchemaSupportFeature .Polymorphism
8080 )
81+ .includeSchemaSupportFeatures (
82+ SchemaSupportFeature .oneOf ,
83+ SchemaSupportFeature .anyOf
84+ )
8185 .excludeParameterFeatures (
8286 ParameterFeature .Cookie
8387 )
@@ -172,6 +176,7 @@ public NimClientCodegen() {
172176 typeMapping .put ("AnyType" , "JsonNode" );
173177 }
174178
179+
175180 @ Override
176181 public ModelsMap postProcessModels (ModelsMap objs ) {
177182 objs = postProcessModelsEnum (objs );
@@ -185,13 +190,26 @@ public ModelsMap postProcessModels(ModelsMap objs) {
185190
186191 // Fix dataType fields that contain underscored type names
187192 // This handles cases like Table[string, Record_string__foo__value]
193+ // Also wrap optional fields in Option[T]
188194 for (CodegenProperty var : cm .vars ) {
189195 if (var .dataType != null && var .dataType .contains ("Record_" )) {
190196 var .dataType = fixRecordTypeReferences (var .dataType );
191197 }
192198 if (var .datatypeWithEnum != null && var .datatypeWithEnum .contains ("Record_" )) {
193199 var .datatypeWithEnum = fixRecordTypeReferences (var .datatypeWithEnum );
194200 }
201+
202+ // Wrap optional (non-required) or nullable fields in Option[T]
203+ if ((!var .required || var .isNullable ) && !var .isReadOnly ) {
204+ String baseType = var .datatypeWithEnum != null ? var .datatypeWithEnum : var .dataType ;
205+ if (baseType != null && !baseType .startsWith ("Option[" )) {
206+ var .dataType = "Option[" + baseType + "]" ;
207+ if (var .datatypeWithEnum != null ) {
208+ var .datatypeWithEnum = "Option[" + var .datatypeWithEnum + "]" ;
209+ }
210+ var .vendorExtensions .put ("x-is-optional" , true );
211+ }
212+ }
195213 }
196214 }
197215
@@ -311,7 +329,75 @@ private String normalizeSchemaName(String name) {
311329 public CodegenModel fromModel (String name , Schema schema ) {
312330 // Normalize the schema name before any processing
313331 name = normalizeSchemaName (name );
314- return super .fromModel (name , schema );
332+ CodegenModel mdl = super .fromModel (name , schema );
333+
334+ // Handle oneOf/anyOf schemas to use Nim object variants
335+ if (mdl .getComposedSchemas () != null ) {
336+ if (mdl .getComposedSchemas ().getOneOf () != null && !mdl .getComposedSchemas ().getOneOf ().isEmpty ()) {
337+ mdl .vendorExtensions .put ("x-is-one-of" , true );
338+ processComposedSchemaVariants (mdl , mdl .getComposedSchemas ().getOneOf (), schema );
339+ } else if (mdl .getComposedSchemas ().getAnyOf () != null && !mdl .getComposedSchemas ().getAnyOf ().isEmpty ()) {
340+ mdl .vendorExtensions .put ("x-is-any-of" , true );
341+ processComposedSchemaVariants (mdl , mdl .getComposedSchemas ().getAnyOf (), schema );
342+ }
343+ }
344+
345+ return mdl ;
346+ }
347+
348+ /**
349+ * Process oneOf/anyOf schemas to generate proper variant names for Nim object variants.
350+ */
351+ private void processComposedSchemaVariants (CodegenModel mdl , List <CodegenProperty > variants , Schema schema ) {
352+ List <CodegenProperty > newVariants = new ArrayList <>();
353+ List <Schema > schemas = ModelUtils .getInterfaces (schema );
354+
355+ if (variants .size () != schemas .size ()) {
356+ LOGGER .warn ("Variant size does not match schema interfaces size for model " + mdl .name );
357+ return ;
358+ }
359+
360+ for (int i = 0 ; i < variants .size (); i ++) {
361+ CodegenProperty variant = variants .get (i );
362+ Schema variantSchema = schemas .get (i );
363+
364+ // Create a clone to avoid modifying the original
365+ CodegenProperty newVariant = variant .clone ();
366+
367+ // Sanitize dataType to remove trailing underscores (Nim doesn't allow them)
368+ if (newVariant .dataType != null ) {
369+ newVariant .dataType = sanitizeNimIdentifier (newVariant .dataType );
370+ }
371+ if (newVariant .datatypeWithEnum != null ) {
372+ newVariant .datatypeWithEnum = sanitizeNimIdentifier (newVariant .datatypeWithEnum );
373+ }
374+
375+ // Set variant name based on schema reference or type
376+ if (variantSchema .get$ref () != null && !variantSchema .get$ref ().isEmpty ()) {
377+ String refName = ModelUtils .getSimpleRef (variantSchema .get$ref ());
378+ if (refName != null ) {
379+ newVariant .setName (toModelName (refName ));
380+ newVariant .setBaseName (refName );
381+ }
382+ } else if (variantSchema .getType () != null ) {
383+ // For primitive types or inline schemas
384+ String typeName = variantSchema .getType ();
385+ if (variantSchema .getTitle () != null && !variantSchema .getTitle ().isEmpty ()) {
386+ typeName = variantSchema .getTitle ();
387+ }
388+ newVariant .setName (camelize (typeName ));
389+ newVariant .setBaseName (typeName );
390+ }
391+
392+ newVariants .add (newVariant );
393+ }
394+
395+ // Replace the original variants with the processed ones
396+ if (mdl .getComposedSchemas ().getOneOf () != null ) {
397+ mdl .getComposedSchemas ().setOneOf (newVariants );
398+ } else if (mdl .getComposedSchemas ().getAnyOf () != null ) {
399+ mdl .getComposedSchemas ().setAnyOf (newVariants );
400+ }
315401 }
316402
317403 @ Override
0 commit comments