@@ -307,6 +307,69 @@ public CodegenModel fromModel(String name, Schema model) {
307307 mdl .getComposedSchemas ().setOneOf (newOneOfs );
308308 }
309309
310+ // Handle anyOf schemas similarly to oneOf
311+ // This is pragmatic since Rust's untagged enum will deserialize to the first matching variant
312+ if (mdl .getComposedSchemas () != null && mdl .getComposedSchemas ().getAnyOf () != null
313+ && !mdl .getComposedSchemas ().getAnyOf ().isEmpty ()) {
314+
315+ List <CodegenProperty > newAnyOfs = mdl .getComposedSchemas ().getAnyOf ().stream ()
316+ .map (CodegenProperty ::clone )
317+ .collect (Collectors .toList ());
318+ List <Schema > schemas = ModelUtils .getInterfaces (model );
319+ if (newAnyOfs .size () != schemas .size ()) {
320+ // For safety reasons, this should never happen unless there is an error in the code
321+ throw new RuntimeException ("anyOf size does not match the model" );
322+ }
323+
324+ Map <String , String > refsMapping = Optional .ofNullable (model .getDiscriminator ())
325+ .map (Discriminator ::getMapping ).orElse (Collections .emptyMap ());
326+
327+ // Reverse mapped references to use as baseName for anyOf, but different keys may point to the same $ref.
328+ // Thus, we group them by the value
329+ Map <String , List <String >> mappedNamesByRef = refsMapping .entrySet ().stream ()
330+ .collect (Collectors .groupingBy (Map .Entry ::getValue ,
331+ Collectors .mapping (Map .Entry ::getKey , Collectors .toList ())
332+ ));
333+
334+ for (int i = 0 ; i < newAnyOfs .size (); i ++) {
335+ CodegenProperty anyOf = newAnyOfs .get (i );
336+ Schema schema = schemas .get (i );
337+
338+ if (mappedNamesByRef .containsKey (schema .get$ref ())) {
339+ // prefer mapped names if present
340+ // remove mapping not in order not to reuse for the next occurrence of the ref
341+ List <String > names = mappedNamesByRef .get (schema .get$ref ());
342+ String mappedName = names .remove (0 );
343+ anyOf .setBaseName (mappedName );
344+ anyOf .setName (toModelName (mappedName ));
345+ } else if (!org .apache .commons .lang3 .StringUtils .isEmpty (schema .get$ref ())) {
346+ // use $ref if it's reference
347+ String refName = ModelUtils .getSimpleRef (schema .get$ref ());
348+ if (refName != null ) {
349+ String modelName = toModelName (refName );
350+ anyOf .setName (modelName );
351+ anyOf .setBaseName (refName );
352+ }
353+ } else if (anyOf .isArray ) {
354+ // If the type is an array, extend the name with the inner type to prevent name collisions
355+ // in case multiple arrays with different types are defined. If the user has manually specified
356+ // a name, use that name instead.
357+ String collectionWithTypeName = toModelName (schema .getType ()) + anyOf .containerTypeMapped + anyOf .items .dataType ;
358+ String anyOfName = Optional .ofNullable (schema .getTitle ()).orElse (collectionWithTypeName );
359+ anyOf .setName (anyOfName );
360+ }
361+ else {
362+ // In-placed type (primitive), because there is no mapping or ref for it.
363+ // use camelized `title` if present, otherwise use `type`
364+ String anyOfName = Optional .ofNullable (schema .getTitle ()).orElseGet (schema ::getType );
365+ anyOf .setName (toModelName (anyOfName ));
366+ }
367+ }
368+
369+ // Set anyOf as oneOf for template processing since we want the same output
370+ mdl .getComposedSchemas ().setOneOf (newAnyOfs );
371+ }
372+
310373 return mdl ;
311374 }
312375
0 commit comments