diff --git a/.changeset/union_fixes.md b/.changeset/union_fixes.md
new file mode 100644
index 000000000..099ef37eb
--- /dev/null
+++ b/.changeset/union_fixes.md
@@ -0,0 +1,7 @@
+---
+default: patch
+---
+
+# Fix class generation for some union types
+
+Fixed issue #1120, where certain combinations of types-- such as a `oneOf` between a model or an enum and null, or the OpenAPI 3.0 equivalent of using `nullable: true`-- could cause unnecessary suffixes like "Type0" to be added to the class name, and/or could cause extra copies of the class to be generated.
diff --git a/end_to_end_tests/baseline_openapi_3.0.json b/end_to_end_tests/baseline_openapi_3.0.json
index 22a786a4f..01fa8fe9e 100644
--- a/end_to_end_tests/baseline_openapi_3.0.json
+++ b/end_to_end_tests/baseline_openapi_3.0.json
@@ -1762,7 +1762,9 @@
           "model",
           "nullable_model",
           "one_of_models",
-          "nullable_one_of_models"
+          "nullable_one_of_models",
+          "nullable_enum_as_ref",
+          "nullable_enum_inline"
         ],
         "type": "object",
         "properties": {
@@ -1951,6 +1953,14 @@
               }
             ],
             "nullable": true
+          },
+          "nullable_enum_as_ref": {
+            "$ref": "#/components/schemas/AnEnumWithNull"
+          },
+          "nullable_enum_inline": {
+            "type": "string",
+            "enum": ["FIRST_VALUE", "SECOND_VALUE", null],
+            "nullable": true
           }
         },
         "description": "A Model for testing all the ways custom objects can be used ",
@@ -1971,6 +1981,7 @@
           "SECOND_VALUE",
           null
         ],
+        "nullable": true,
         "description": "For testing Enums with mixed string / null values "
       },
       "AnEnumWithOnlyNull": {
diff --git a/end_to_end_tests/baseline_openapi_3.1.yaml b/end_to_end_tests/baseline_openapi_3.1.yaml
index a19e46ce3..651c50ebd 100644
--- a/end_to_end_tests/baseline_openapi_3.1.yaml
+++ b/end_to_end_tests/baseline_openapi_3.1.yaml
@@ -1747,7 +1747,9 @@ info:
         "model",
         "nullable_model",
         "one_of_models",
-        "nullable_one_of_models"
+        "nullable_one_of_models",
+        "nullable_enum_as_ref",
+        "nullable_enum_inline"
       ],
       "type": "object",
       "properties": {
@@ -1950,6 +1952,13 @@ info:
               "$ref": "#/components/schemas/ModelWithUnionProperty"
             }
           ]
+        },
+        "nullable_enum_as_ref": {
+          "$ref": "#/components/schemas/AnEnumWithNull"
+        },
+        "nullable_enum_inline": {
+          "type": ["string", "null"],
+          "enum": ["FIRST_VALUE", "SECOND_VALUE", null]
         }
       },
       "description": "A Model for testing all the ways custom objects can be used ",
@@ -1965,6 +1974,7 @@ info:
     },
     "AnEnumWithNull": {
       "title": "AnEnumWithNull",
+      "type": ["string", "null"],
       "enum": [
         "FIRST_VALUE",
         "SECOND_VALUE",
diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py
index f354c31c7..14fd3d92e 100644
--- a/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py
+++ b/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py
@@ -4,6 +4,7 @@
 from .a_discriminated_union_type_2 import ADiscriminatedUnionType2
 from .a_form_data import AFormData
 from .a_model import AModel
+from .a_model_nullable_enum_inline import AModelNullableEnumInline
 from .a_model_with_properties_reference_that_are_not_object import AModelWithPropertiesReferenceThatAreNotObject
 from .all_of_has_properties_but_no_type import AllOfHasPropertiesButNoType
 from .all_of_has_properties_but_no_type_type_enum import AllOfHasPropertiesButNoTypeTypeEnum
@@ -54,7 +55,7 @@
 )
 from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed
 from .model_with_any_json_properties import ModelWithAnyJsonProperties
-from .model_with_any_json_properties_additional_property_type_0 import ModelWithAnyJsonPropertiesAdditionalPropertyType0
+from .model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty
 from .model_with_backslash_in_description import ModelWithBackslashInDescription
 from .model_with_circular_ref_a import ModelWithCircularRefA
 from .model_with_circular_ref_b import ModelWithCircularRefB
@@ -82,8 +83,8 @@
 from .post_naming_property_conflict_with_import_body import PostNamingPropertyConflictWithImportBody
 from .post_naming_property_conflict_with_import_response_200 import PostNamingPropertyConflictWithImportResponse200
 from .post_responses_unions_simple_before_complex_response_200 import PostResponsesUnionsSimpleBeforeComplexResponse200
-from .post_responses_unions_simple_before_complex_response_200a_type_1 import (
-    PostResponsesUnionsSimpleBeforeComplexResponse200AType1,
+from .post_responses_unions_simple_before_complex_response_200a import (
+    PostResponsesUnionsSimpleBeforeComplexResponse200A,
 )
 from .test_inline_objects_body import TestInlineObjectsBody
 from .test_inline_objects_response_200 import TestInlineObjectsResponse200
@@ -98,6 +99,7 @@
     "AllOfSubModel",
     "AllOfSubModelTypeEnum",
     "AModel",
+    "AModelNullableEnumInline",
     "AModelWithPropertiesReferenceThatAreNotObject",
     "AnAllOfEnum",
     "AnArrayWithACircularRefInItemsObjectAdditionalPropertiesAItem",
@@ -136,7 +138,7 @@
     "ModelWithAdditionalPropertiesInlinedAdditionalProperty",
     "ModelWithAdditionalPropertiesRefed",
     "ModelWithAnyJsonProperties",
-    "ModelWithAnyJsonPropertiesAdditionalPropertyType0",
+    "ModelWithAnyJsonPropertiesAdditionalProperty",
     "ModelWithBackslashInDescription",
     "ModelWithCircularRefA",
     "ModelWithCircularRefB",
@@ -164,7 +166,7 @@
     "PostNamingPropertyConflictWithImportBody",
     "PostNamingPropertyConflictWithImportResponse200",
     "PostResponsesUnionsSimpleBeforeComplexResponse200",
-    "PostResponsesUnionsSimpleBeforeComplexResponse200AType1",
+    "PostResponsesUnionsSimpleBeforeComplexResponse200A",
     "TestInlineObjectsBody",
     "TestInlineObjectsResponse200",
     "ValidationError",
diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py
index 5a81e6365..54329e73a 100644
--- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py
+++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py
@@ -5,8 +5,10 @@
 from attrs import define as _attrs_define
 from dateutil.parser import isoparse
 
+from ..models.a_model_nullable_enum_inline import AModelNullableEnumInline
 from ..models.an_all_of_enum import AnAllOfEnum
 from ..models.an_enum import AnEnum
+from ..models.an_enum_with_null import AnEnumWithNull
 from ..models.different_enum import DifferentEnum
 from ..types import UNSET, Unset
 
@@ -36,6 +38,8 @@ class AModel:
         nullable_one_of_models (Union['FreeFormModel', 'ModelWithUnionProperty', None]):
         model (ModelWithUnionProperty):
         nullable_model (Union['ModelWithUnionProperty', None]):
+        nullable_enum_as_ref (Union[AnEnumWithNull, None]): For testing Enums with mixed string / null values
+        nullable_enum_inline (Union[AModelNullableEnumInline, None]):
         any_value (Union[Unset, Any]):  Default: 'default'.
         an_optional_allof_enum (Union[Unset, AnAllOfEnum]):
         nested_list_of_enums (Union[Unset, list[list[DifferentEnum]]]):
@@ -62,6 +66,8 @@ class AModel:
     nullable_one_of_models: Union["FreeFormModel", "ModelWithUnionProperty", None]
     model: "ModelWithUnionProperty"
     nullable_model: Union["ModelWithUnionProperty", None]
+    nullable_enum_as_ref: Union[AnEnumWithNull, None]
+    nullable_enum_inline: Union[AModelNullableEnumInline, None]
     an_allof_enum_with_overridden_default: AnAllOfEnum = AnAllOfEnum.OVERRIDDEN_DEFAULT
     a_nullable_uuid: Union[None, UUID] = UUID("07EF8B4D-AA09-4FFA-898D-C710796AFF41")
     any_value: Union[Unset, Any] = "default"
@@ -137,6 +143,18 @@ def to_dict(self) -> dict[str, Any]:
         else:
             nullable_model = self.nullable_model
 
+        nullable_enum_as_ref: Union[None, str]
+        if isinstance(self.nullable_enum_as_ref, AnEnumWithNull):
+            nullable_enum_as_ref = self.nullable_enum_as_ref.value
+        else:
+            nullable_enum_as_ref = self.nullable_enum_as_ref
+
+        nullable_enum_inline: Union[None, str]
+        if isinstance(self.nullable_enum_inline, AModelNullableEnumInline):
+            nullable_enum_inline = self.nullable_enum_inline.value
+        else:
+            nullable_enum_inline = self.nullable_enum_inline
+
         any_value = self.any_value
 
         an_optional_allof_enum: Union[Unset, str] = UNSET
@@ -220,6 +238,8 @@ def to_dict(self) -> dict[str, Any]:
                 "nullable_one_of_models": nullable_one_of_models,
                 "model": model,
                 "nullable_model": nullable_model,
+                "nullable_enum_as_ref": nullable_enum_as_ref,
+                "nullable_enum_inline": nullable_enum_inline,
             }
         )
         if any_value is not UNSET:
@@ -373,15 +393,45 @@ def _parse_nullable_model(data: object) -> Union["ModelWithUnionProperty", None]
             try:
                 if not isinstance(data, dict):
                     raise TypeError()
-                nullable_model_type_1 = ModelWithUnionProperty.from_dict(data)
+                nullable_model = ModelWithUnionProperty.from_dict(data)
 
-                return nullable_model_type_1
+                return nullable_model
             except:  # noqa: E722
                 pass
             return cast(Union["ModelWithUnionProperty", None], data)
 
         nullable_model = _parse_nullable_model(d.pop("nullable_model"))
 
+        def _parse_nullable_enum_as_ref(data: object) -> Union[AnEnumWithNull, None]:
+            if data is None:
+                return data
+            try:
+                if not isinstance(data, str):
+                    raise TypeError()
+                componentsschemas_an_enum_with_null = AnEnumWithNull(data)
+
+                return componentsschemas_an_enum_with_null
+            except:  # noqa: E722
+                pass
+            return cast(Union[AnEnumWithNull, None], data)
+
+        nullable_enum_as_ref = _parse_nullable_enum_as_ref(d.pop("nullable_enum_as_ref"))
+
+        def _parse_nullable_enum_inline(data: object) -> Union[AModelNullableEnumInline, None]:
+            if data is None:
+                return data
+            try:
+                if not isinstance(data, str):
+                    raise TypeError()
+                nullable_enum_inline = AModelNullableEnumInline(data)
+
+                return nullable_enum_inline
+            except:  # noqa: E722
+                pass
+            return cast(Union[AModelNullableEnumInline, None], data)
+
+        nullable_enum_inline = _parse_nullable_enum_inline(d.pop("nullable_enum_inline"))
+
         any_value = d.pop("any_value", UNSET)
 
         _an_optional_allof_enum = d.pop("an_optional_allof_enum", UNSET)
@@ -495,9 +545,9 @@ def _parse_not_required_nullable_model(data: object) -> Union["ModelWithUnionPro
             try:
                 if not isinstance(data, dict):
                     raise TypeError()
-                not_required_nullable_model_type_1 = ModelWithUnionProperty.from_dict(data)
+                not_required_nullable_model = ModelWithUnionProperty.from_dict(data)
 
-                return not_required_nullable_model_type_1
+                return not_required_nullable_model
             except:  # noqa: E722
                 pass
             return cast(Union["ModelWithUnionProperty", None, Unset], data)
@@ -518,6 +568,8 @@ def _parse_not_required_nullable_model(data: object) -> Union["ModelWithUnionPro
             nullable_one_of_models=nullable_one_of_models,
             model=model,
             nullable_model=nullable_model,
+            nullable_enum_as_ref=nullable_enum_as_ref,
+            nullable_enum_inline=nullable_enum_inline,
             any_value=any_value,
             an_optional_allof_enum=an_optional_allof_enum,
             nested_list_of_enums=nested_list_of_enums,
diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model_nullable_enum_inline.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model_nullable_enum_inline.py
new file mode 100644
index 000000000..21634624e
--- /dev/null
+++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model_nullable_enum_inline.py
@@ -0,0 +1,9 @@
+from enum import Enum
+
+
+class AModelNullableEnumInline(str, Enum):
+    FIRST_VALUE = "FIRST_VALUE"
+    SECOND_VALUE = "SECOND_VALUE"
+
+    def __str__(self) -> str:
+        return str(self.value)
diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py
index 1c255cfcb..4bcc53863 100644
--- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py
+++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py
@@ -304,9 +304,9 @@ def _parse_some_nullable_object(data: object) -> Union["BodyUploadFileTestsUploa
             try:
                 if not isinstance(data, dict):
                     raise TypeError()
-                some_nullable_object_type_0 = BodyUploadFileTestsUploadPostSomeNullableObject.from_dict(data)
+                some_nullable_object = BodyUploadFileTestsUploadPostSomeNullableObject.from_dict(data)
 
-                return some_nullable_object_type_0
+                return some_nullable_object
             except:  # noqa: E722
                 pass
             return cast(Union["BodyUploadFileTestsUploadPostSomeNullableObject", None], data)
diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/extended.py b/end_to_end_tests/golden-record/my_test_api_client/models/extended.py
index ffd6406c7..cc67ad784 100644
--- a/end_to_end_tests/golden-record/my_test_api_client/models/extended.py
+++ b/end_to_end_tests/golden-record/my_test_api_client/models/extended.py
@@ -6,8 +6,10 @@
 from attrs import field as _attrs_field
 from dateutil.parser import isoparse
 
+from ..models.a_model_nullable_enum_inline import AModelNullableEnumInline
 from ..models.an_all_of_enum import AnAllOfEnum
 from ..models.an_enum import AnEnum
+from ..models.an_enum_with_null import AnEnumWithNull
 from ..models.different_enum import DifferentEnum
 from ..types import UNSET, Unset
 
@@ -36,6 +38,8 @@ class Extended:
         nullable_one_of_models (Union['FreeFormModel', 'ModelWithUnionProperty', None]):
         model (ModelWithUnionProperty):
         nullable_model (Union['ModelWithUnionProperty', None]):
+        nullable_enum_as_ref (Union[AnEnumWithNull, None]): For testing Enums with mixed string / null values
+        nullable_enum_inline (Union[AModelNullableEnumInline, None]):
         any_value (Union[Unset, Any]):  Default: 'default'.
         an_optional_allof_enum (Union[Unset, AnAllOfEnum]):
         nested_list_of_enums (Union[Unset, list[list[DifferentEnum]]]):
@@ -63,6 +67,8 @@ class Extended:
     nullable_one_of_models: Union["FreeFormModel", "ModelWithUnionProperty", None]
     model: "ModelWithUnionProperty"
     nullable_model: Union["ModelWithUnionProperty", None]
+    nullable_enum_as_ref: Union[AnEnumWithNull, None]
+    nullable_enum_inline: Union[AModelNullableEnumInline, None]
     an_allof_enum_with_overridden_default: AnAllOfEnum = AnAllOfEnum.OVERRIDDEN_DEFAULT
     a_nullable_uuid: Union[None, UUID] = UUID("07EF8B4D-AA09-4FFA-898D-C710796AFF41")
     any_value: Union[Unset, Any] = "default"
@@ -140,6 +146,18 @@ def to_dict(self) -> dict[str, Any]:
         else:
             nullable_model = self.nullable_model
 
+        nullable_enum_as_ref: Union[None, str]
+        if isinstance(self.nullable_enum_as_ref, AnEnumWithNull):
+            nullable_enum_as_ref = self.nullable_enum_as_ref.value
+        else:
+            nullable_enum_as_ref = self.nullable_enum_as_ref
+
+        nullable_enum_inline: Union[None, str]
+        if isinstance(self.nullable_enum_inline, AModelNullableEnumInline):
+            nullable_enum_inline = self.nullable_enum_inline.value
+        else:
+            nullable_enum_inline = self.nullable_enum_inline
+
         any_value = self.any_value
 
         an_optional_allof_enum: Union[Unset, str] = UNSET
@@ -226,6 +244,8 @@ def to_dict(self) -> dict[str, Any]:
                 "nullable_one_of_models": nullable_one_of_models,
                 "model": model,
                 "nullable_model": nullable_model,
+                "nullable_enum_as_ref": nullable_enum_as_ref,
+                "nullable_enum_inline": nullable_enum_inline,
             }
         )
         if any_value is not UNSET:
@@ -381,15 +401,45 @@ def _parse_nullable_model(data: object) -> Union["ModelWithUnionProperty", None]
             try:
                 if not isinstance(data, dict):
                     raise TypeError()
-                nullable_model_type_1 = ModelWithUnionProperty.from_dict(data)
+                nullable_model = ModelWithUnionProperty.from_dict(data)
 
-                return nullable_model_type_1
+                return nullable_model
             except:  # noqa: E722
                 pass
             return cast(Union["ModelWithUnionProperty", None], data)
 
         nullable_model = _parse_nullable_model(d.pop("nullable_model"))
 
+        def _parse_nullable_enum_as_ref(data: object) -> Union[AnEnumWithNull, None]:
+            if data is None:
+                return data
+            try:
+                if not isinstance(data, str):
+                    raise TypeError()
+                componentsschemas_an_enum_with_null = AnEnumWithNull(data)
+
+                return componentsschemas_an_enum_with_null
+            except:  # noqa: E722
+                pass
+            return cast(Union[AnEnumWithNull, None], data)
+
+        nullable_enum_as_ref = _parse_nullable_enum_as_ref(d.pop("nullable_enum_as_ref"))
+
+        def _parse_nullable_enum_inline(data: object) -> Union[AModelNullableEnumInline, None]:
+            if data is None:
+                return data
+            try:
+                if not isinstance(data, str):
+                    raise TypeError()
+                nullable_enum_inline = AModelNullableEnumInline(data)
+
+                return nullable_enum_inline
+            except:  # noqa: E722
+                pass
+            return cast(Union[AModelNullableEnumInline, None], data)
+
+        nullable_enum_inline = _parse_nullable_enum_inline(d.pop("nullable_enum_inline"))
+
         any_value = d.pop("any_value", UNSET)
 
         _an_optional_allof_enum = d.pop("an_optional_allof_enum", UNSET)
@@ -503,9 +553,9 @@ def _parse_not_required_nullable_model(data: object) -> Union["ModelWithUnionPro
             try:
                 if not isinstance(data, dict):
                     raise TypeError()
-                not_required_nullable_model_type_1 = ModelWithUnionProperty.from_dict(data)
+                not_required_nullable_model = ModelWithUnionProperty.from_dict(data)
 
-                return not_required_nullable_model_type_1
+                return not_required_nullable_model
             except:  # noqa: E722
                 pass
             return cast(Union["ModelWithUnionProperty", None, Unset], data)
@@ -528,6 +578,8 @@ def _parse_not_required_nullable_model(data: object) -> Union["ModelWithUnionPro
             nullable_one_of_models=nullable_one_of_models,
             model=model,
             nullable_model=nullable_model,
+            nullable_enum_as_ref=nullable_enum_as_ref,
+            nullable_enum_inline=nullable_enum_inline,
             any_value=any_value,
             an_optional_allof_enum=an_optional_allof_enum,
             nested_list_of_enums=nested_list_of_enums,
diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py
index f71fe7c1e..deb8aeea5 100644
--- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py
+++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py
@@ -4,9 +4,7 @@
 from attrs import field as _attrs_field
 
 if TYPE_CHECKING:
-    from ..models.model_with_any_json_properties_additional_property_type_0 import (
-        ModelWithAnyJsonPropertiesAdditionalPropertyType0,
-    )
+    from ..models.model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty
 
 
 T = TypeVar("T", bound="ModelWithAnyJsonProperties")
@@ -17,17 +15,17 @@ class ModelWithAnyJsonProperties:
     """ """
 
     additional_properties: dict[
-        str, Union["ModelWithAnyJsonPropertiesAdditionalPropertyType0", bool, float, int, list[str], str]
+        str, Union["ModelWithAnyJsonPropertiesAdditionalProperty", bool, float, int, list[str], str]
     ] = _attrs_field(init=False, factory=dict)
 
     def to_dict(self) -> dict[str, Any]:
-        from ..models.model_with_any_json_properties_additional_property_type_0 import (
-            ModelWithAnyJsonPropertiesAdditionalPropertyType0,
+        from ..models.model_with_any_json_properties_additional_property import (
+            ModelWithAnyJsonPropertiesAdditionalProperty,
         )
 
         field_dict: dict[str, Any] = {}
         for prop_name, prop in self.additional_properties.items():
-            if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalPropertyType0):
+            if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalProperty):
                 field_dict[prop_name] = prop.to_dict()
             elif isinstance(prop, list):
                 field_dict[prop_name] = prop
@@ -39,8 +37,8 @@ def to_dict(self) -> dict[str, Any]:
 
     @classmethod
     def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
-        from ..models.model_with_any_json_properties_additional_property_type_0 import (
-            ModelWithAnyJsonPropertiesAdditionalPropertyType0,
+        from ..models.model_with_any_json_properties_additional_property import (
+            ModelWithAnyJsonPropertiesAdditionalProperty,
         )
 
         d = src_dict.copy()
@@ -51,13 +49,13 @@ def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
 
             def _parse_additional_property(
                 data: object,
-            ) -> Union["ModelWithAnyJsonPropertiesAdditionalPropertyType0", bool, float, int, list[str], str]:
+            ) -> Union["ModelWithAnyJsonPropertiesAdditionalProperty", bool, float, int, list[str], str]:
                 try:
                     if not isinstance(data, dict):
                         raise TypeError()
-                    additional_property_type_0 = ModelWithAnyJsonPropertiesAdditionalPropertyType0.from_dict(data)
+                    additional_property = ModelWithAnyJsonPropertiesAdditionalProperty.from_dict(data)
 
-                    return additional_property_type_0
+                    return additional_property
                 except:  # noqa: E722
                     pass
                 try:
@@ -69,7 +67,7 @@ def _parse_additional_property(
                 except:  # noqa: E722
                     pass
                 return cast(
-                    Union["ModelWithAnyJsonPropertiesAdditionalPropertyType0", bool, float, int, list[str], str], data
+                    Union["ModelWithAnyJsonPropertiesAdditionalProperty", bool, float, int, list[str], str], data
                 )
 
             additional_property = _parse_additional_property(prop_dict)
@@ -85,13 +83,11 @@ def additional_keys(self) -> list[str]:
 
     def __getitem__(
         self, key: str
-    ) -> Union["ModelWithAnyJsonPropertiesAdditionalPropertyType0", bool, float, int, list[str], str]:
+    ) -> Union["ModelWithAnyJsonPropertiesAdditionalProperty", bool, float, int, list[str], str]:
         return self.additional_properties[key]
 
     def __setitem__(
-        self,
-        key: str,
-        value: Union["ModelWithAnyJsonPropertiesAdditionalPropertyType0", bool, float, int, list[str], str],
+        self, key: str, value: Union["ModelWithAnyJsonPropertiesAdditionalProperty", bool, float, int, list[str], str]
     ) -> None:
         self.additional_properties[key] = value
 
diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py
similarity index 82%
rename from end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py
rename to end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py
index 65993e8be..e7e244eb7 100644
--- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property_type_0.py
+++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py
@@ -3,11 +3,11 @@
 from attrs import define as _attrs_define
 from attrs import field as _attrs_field
 
-T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalPropertyType0")
+T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalProperty")
 
 
 @_attrs_define
-class ModelWithAnyJsonPropertiesAdditionalPropertyType0:
+class ModelWithAnyJsonPropertiesAdditionalProperty:
     """ """
 
     additional_properties: dict[str, str] = _attrs_field(init=False, factory=dict)
@@ -21,10 +21,10 @@ def to_dict(self) -> dict[str, Any]:
     @classmethod
     def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
         d = src_dict.copy()
-        model_with_any_json_properties_additional_property_type_0 = cls()
+        model_with_any_json_properties_additional_property = cls()
 
-        model_with_any_json_properties_additional_property_type_0.additional_properties = d
-        return model_with_any_json_properties_additional_property_type_0
+        model_with_any_json_properties_additional_property.additional_properties = d
+        return model_with_any_json_properties_additional_property
 
     @property
     def additional_keys(self) -> list[str]:
diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py
index 9962f552c..51f6dade2 100644
--- a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py
+++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200.py
@@ -4,8 +4,8 @@
 from attrs import field as _attrs_field
 
 if TYPE_CHECKING:
-    from ..models.post_responses_unions_simple_before_complex_response_200a_type_1 import (
-        PostResponsesUnionsSimpleBeforeComplexResponse200AType1,
+    from ..models.post_responses_unions_simple_before_complex_response_200a import (
+        PostResponsesUnionsSimpleBeforeComplexResponse200A,
     )
 
 
@@ -16,19 +16,19 @@
 class PostResponsesUnionsSimpleBeforeComplexResponse200:
     """
     Attributes:
-        a (Union['PostResponsesUnionsSimpleBeforeComplexResponse200AType1', str]):
+        a (Union['PostResponsesUnionsSimpleBeforeComplexResponse200A', str]):
     """
 
-    a: Union["PostResponsesUnionsSimpleBeforeComplexResponse200AType1", str]
+    a: Union["PostResponsesUnionsSimpleBeforeComplexResponse200A", str]
     additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
 
     def to_dict(self) -> dict[str, Any]:
-        from ..models.post_responses_unions_simple_before_complex_response_200a_type_1 import (
-            PostResponsesUnionsSimpleBeforeComplexResponse200AType1,
+        from ..models.post_responses_unions_simple_before_complex_response_200a import (
+            PostResponsesUnionsSimpleBeforeComplexResponse200A,
         )
 
         a: Union[dict[str, Any], str]
-        if isinstance(self.a, PostResponsesUnionsSimpleBeforeComplexResponse200AType1):
+        if isinstance(self.a, PostResponsesUnionsSimpleBeforeComplexResponse200A):
             a = self.a.to_dict()
         else:
             a = self.a
@@ -45,22 +45,22 @@ def to_dict(self) -> dict[str, Any]:
 
     @classmethod
     def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
-        from ..models.post_responses_unions_simple_before_complex_response_200a_type_1 import (
-            PostResponsesUnionsSimpleBeforeComplexResponse200AType1,
+        from ..models.post_responses_unions_simple_before_complex_response_200a import (
+            PostResponsesUnionsSimpleBeforeComplexResponse200A,
         )
 
         d = src_dict.copy()
 
-        def _parse_a(data: object) -> Union["PostResponsesUnionsSimpleBeforeComplexResponse200AType1", str]:
+        def _parse_a(data: object) -> Union["PostResponsesUnionsSimpleBeforeComplexResponse200A", str]:
             try:
                 if not isinstance(data, dict):
                     raise TypeError()
-                a_type_1 = PostResponsesUnionsSimpleBeforeComplexResponse200AType1.from_dict(data)
+                a = PostResponsesUnionsSimpleBeforeComplexResponse200A.from_dict(data)
 
-                return a_type_1
+                return a
             except:  # noqa: E722
                 pass
-            return cast(Union["PostResponsesUnionsSimpleBeforeComplexResponse200AType1", str], data)
+            return cast(Union["PostResponsesUnionsSimpleBeforeComplexResponse200A", str], data)
 
         a = _parse_a(d.pop("a"))
 
diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a.py
similarity index 89%
rename from end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py
rename to end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a.py
index 5e8ef0207..be97429f5 100644
--- a/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a_type_1.py
+++ b/end_to_end_tests/golden-record/my_test_api_client/models/post_responses_unions_simple_before_complex_response_200a.py
@@ -3,11 +3,11 @@
 from attrs import define as _attrs_define
 from attrs import field as _attrs_field
 
-T = TypeVar("T", bound="PostResponsesUnionsSimpleBeforeComplexResponse200AType1")
+T = TypeVar("T", bound="PostResponsesUnionsSimpleBeforeComplexResponse200A")
 
 
 @_attrs_define
-class PostResponsesUnionsSimpleBeforeComplexResponse200AType1:
+class PostResponsesUnionsSimpleBeforeComplexResponse200A:
     """ """
 
     additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
@@ -21,10 +21,10 @@ def to_dict(self) -> dict[str, Any]:
     @classmethod
     def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
         d = src_dict.copy()
-        post_responses_unions_simple_before_complex_response_200a_type_1 = cls()
+        post_responses_unions_simple_before_complex_response_200a = cls()
 
-        post_responses_unions_simple_before_complex_response_200a_type_1.additional_properties = d
-        return post_responses_unions_simple_before_complex_response_200a_type_1
+        post_responses_unions_simple_before_complex_response_200a.additional_properties = d
+        return post_responses_unions_simple_before_complex_response_200a
 
     @property
     def additional_keys(self) -> list[str]:
diff --git a/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/post_user_list_body.py b/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/post_user_list_body.py
index 5566f1b3b..6af995f66 100644
--- a/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/post_user_list_body.py
+++ b/end_to_end_tests/literal-enums-golden-record/my_enum_api_client/models/post_user_list_body.py
@@ -187,9 +187,9 @@ def _parse_an_enum_value_with_null_item(data: object) -> Union[AnEnumWithNull, N
                 try:
                     if not isinstance(data, str):
                         raise TypeError()
-                    componentsschemas_an_enum_with_null_type_1 = check_an_enum_with_null(data)
+                    componentsschemas_an_enum_with_null = check_an_enum_with_null(data)
 
-                    return componentsschemas_an_enum_with_null_type_1
+                    return componentsschemas_an_enum_with_null
                 except:  # noqa: E722
                     pass
                 return cast(Union[AnEnumWithNull, None], data)
diff --git a/openapi_python_client/parser/properties/enum_property.py b/openapi_python_client/parser/properties/enum_property.py
index fc7f20bd9..6007ce4f1 100644
--- a/openapi_python_client/parser/properties/enum_property.py
+++ b/openapi_python_client/parser/properties/enum_property.py
@@ -1,5 +1,8 @@
 from __future__ import annotations
 
+from openapi_python_client.parser.properties.has_named_class import HasNamedClass
+from openapi_python_client.schema.data_type import DataType
+
 __all__ = ["EnumProperty", "ValueType"]
 
 from typing import Any, ClassVar, Union, cast
@@ -9,7 +12,6 @@
 
 from ... import Config, utils
 from ... import schema as oai
-from ...schema import DataType
 from ..errors import PropertyError
 from .none import NoneProperty
 from .protocol import PropertyProtocol, Value
@@ -20,7 +22,7 @@
 
 
 @define
-class EnumProperty(PropertyProtocol):
+class EnumProperty(PropertyProtocol, HasNamedClass):
     """A property that should use an enum"""
 
     name: str
@@ -75,9 +77,10 @@ def build(  # noqa: PLR0911
         # So instead, if null is a possible value, make the property nullable.
         # Mypy is not smart enough to know that the type is right though
         unchecked_value_list = [value for value in enum if value is not None]  # type: ignore
+        allow_null = len(unchecked_value_list) < len(enum)
 
         # It's legal to have an enum that only contains null as a value, we don't bother constructing an enum for that
-        if len(unchecked_value_list) == 0:
+        if len(unchecked_value_list) == 0 and allow_null:
             return (
                 NoneProperty.build(
                     name=name,
@@ -102,7 +105,7 @@ def build(  # noqa: PLR0911
             Union[list[int], list[str]], unchecked_value_list
         )  # We checked this with all the value_types stuff
 
-        if len(value_list) < len(enum):  # Only one of the values was None, that becomes a union
+        if allow_null:  # Only one of the values was None, that becomes a union
             data.oneOf = [
                 oai.Schema(type=DataType.NULL),
                 data.model_copy(update={"enum": value_list, "default": data.default}),
diff --git a/openapi_python_client/parser/properties/has_named_class.py b/openapi_python_client/parser/properties/has_named_class.py
new file mode 100644
index 000000000..d24b77420
--- /dev/null
+++ b/openapi_python_client/parser/properties/has_named_class.py
@@ -0,0 +1,8 @@
+from typing import Protocol, runtime_checkable
+
+from .schemas import Class
+
+
+@runtime_checkable
+class HasNamedClass(Protocol):
+    class_info: Class
diff --git a/openapi_python_client/parser/properties/model_property.py b/openapi_python_client/parser/properties/model_property.py
index 762624501..83ba86063 100644
--- a/openapi_python_client/parser/properties/model_property.py
+++ b/openapi_python_client/parser/properties/model_property.py
@@ -5,6 +5,8 @@
 
 from attrs import define, evolve
 
+from openapi_python_client.parser.properties.has_named_class import HasNamedClass
+
 from ... import Config, utils
 from ... import schema as oai
 from ...utils import PythonIdentifier
@@ -15,7 +17,7 @@
 
 
 @define
-class ModelProperty(PropertyProtocol):
+class ModelProperty(PropertyProtocol, HasNamedClass):
     """A property which refers to another Schema"""
 
     name: str
diff --git a/openapi_python_client/parser/properties/union.py b/openapi_python_client/parser/properties/union.py
index 8b7b02a48..32c9b5288 100644
--- a/openapi_python_client/parser/properties/union.py
+++ b/openapi_python_client/parser/properties/union.py
@@ -1,10 +1,12 @@
 from __future__ import annotations
 
 from itertools import chain
-from typing import Any, ClassVar, cast
+from typing import Any, Callable, ClassVar, cast
 
 from attr import define, evolve
 
+from openapi_python_client.parser.properties.has_named_class import HasNamedClass
+
 from ... import Config
 from ... import schema as oai
 from ...utils import PythonIdentifier
@@ -47,25 +49,92 @@ def build(
         """
         from . import property_from_data
 
-        sub_properties: list[PropertyProtocol] = []
-
         type_list_data = []
-        if isinstance(data.type, list):
+        if isinstance(data.type, list) and not (data.anyOf or data.oneOf):
+            # The schema specifies "type:" with a list of allowable types. If there is *not* also an "anyOf"
+            # or "oneOf", then we should treat that as a shorthand for a oneOf where each variant is just
+            # a single "type:". For example:
+            #   {"type": ["string", "int"]} becomes
+            #   {"oneOf": [{"type": "string"}, {"type": "int"}]}
+            # However, if there *is* also an "anyOf" or "oneOf" list, then the information from "type:" is
+            # redundant since every allowable variant type is already fully described in the list.
             for _type in data.type:
                 type_list_data.append(data.model_copy(update={"type": _type, "default": None}))
+                # Here we're copying properties from the top-level union schema that might apply to one
+                # of the type variants, like "format" for a string. But we don't copy "default" because
+                # default values will be handled at the top level by the UnionProperty.
+
+        def _add_index_suffix_to_variant_names(index: int) -> str:
+            return f"{name}_type_{index}"
+
+        def process_items(
+            variant_name_from_index_func: Callable[[int], str] = _add_index_suffix_to_variant_names,
+        ) -> tuple[list[PropertyProtocol] | PropertyError, Schemas]:
+            props: list[PropertyProtocol] = []
+            new_schemas = schemas
+            for i, sub_prop_data in enumerate(chain(data.anyOf, data.oneOf, type_list_data)):
+                sub_prop_name = variant_name_from_index_func(i)
+
+                # The sub_prop_name logic is what makes this a bit complicated. That value is used only
+                # if sub_prop is an *inline* schema and needs us to make up a name for it. For instance,
+                # in the following schema--
+                #
+                #   MyModel:
+                #     properties:
+                #       unionThing:
+                #         oneOf:
+                #           - type: object
+                #             properties: ...
+                #           - type: object
+                #             properties: ...
+                #
+                # --both of the variants under oneOf are inline schemas. And since they're objects, we
+                # will be creating model classes for them, which need names. Inline schemas are named by
+                # concatenating names of parents; so, when we're in UnionProperty.build() for unionThing,
+                # the value of "name" is "my_model_union_thing", and then we set sub_prop_name to
+                # "my_model_union_thing_type_0" and "my_model_union_thing_type_1" for the two variants,
+                # and their model classes will be MyModelUnionThingType0 and MyModelUnionThingType1.
+                #
+                # However, in this example, if the second variant was just a scalar type instead of an
+                # object (like "type: null" or "type: string"), so that the first variant is the only
+                # one that needs a class... then it would be friendlier to call the first variant's
+                # class just MyModelUnionThing, not MyModelUnionThingType0. We'll check for that special
+                # case below; we can't know if that's the situation until after we've processed them all.
+
+                sub_prop, new_schemas = property_from_data(
+                    name=sub_prop_name,
+                    required=True,
+                    data=sub_prop_data,
+                    schemas=new_schemas,
+                    parent_name=parent_name,
+                    config=config,
+                )
+                if isinstance(sub_prop, PropertyError):
+                    return PropertyError(detail=f"Invalid property in union {name}", data=sub_prop_data), new_schemas
+                props.append(sub_prop)
+
+            return props, new_schemas
+
+        sub_properties, new_schemas = process_items()
+        # Here's the check for the special case described above. If just one of the variants is
+        # an inline schema whose name matters, then we'll re-process them to simplify the naming.
+        # Unfortunately we do have to re-process them all; we can't just modify that one variant
+        # in place, because new_schemas already contains several references to its old name.
+        if not isinstance(sub_properties, PropertyError):
+            if len([p for p in sub_properties if isinstance(p, HasNamedClass)]) == 1:
+                original_sub_props = sub_properties
+
+                def _use_same_name_as_parent_for_that_one_variant(index: int) -> str:
+                    for i, p in enumerate(original_sub_props):
+                        if i == index and isinstance(p, HasNamedClass):
+                            return name
+                    return _add_index_suffix_to_variant_names(index)
+
+                sub_properties, new_schemas = process_items(_use_same_name_as_parent_for_that_one_variant)
 
-        for i, sub_prop_data in enumerate(chain(data.anyOf, data.oneOf, type_list_data)):
-            sub_prop, schemas = property_from_data(
-                name=f"{name}_type_{i}",
-                required=True,
-                data=sub_prop_data,
-                schemas=schemas,
-                parent_name=parent_name,
-                config=config,
-            )
-            if isinstance(sub_prop, PropertyError):
-                return PropertyError(detail=f"Invalid property in union {name}", data=sub_prop_data), schemas
-            sub_properties.append(sub_prop)
+        if isinstance(sub_properties, PropertyError):
+            return sub_properties, schemas
+        schemas = new_schemas
 
         def flatten_union_properties(sub_properties: list[PropertyProtocol]) -> list[PropertyProtocol]:
             flattened = []
diff --git a/tests/test_parser/test_properties/test_enum_property.py b/tests/test_parser/test_properties/test_enum_property.py
index 282298aaf..dfcf6970d 100644
--- a/tests/test_parser/test_properties/test_enum_property.py
+++ b/tests/test_parser/test_properties/test_enum_property.py
@@ -5,8 +5,13 @@
 import openapi_python_client.schema as oai
 from openapi_python_client import Config
 from openapi_python_client.parser.errors import PropertyError
-from openapi_python_client.parser.properties import LiteralEnumProperty, Schemas
-from openapi_python_client.parser.properties.enum_property import EnumProperty
+from openapi_python_client.parser.properties import (
+    EnumProperty,
+    LiteralEnumProperty,
+    NoneProperty,
+    Schemas,
+    UnionProperty,
+)
 
 PropertyClass = Union[type[EnumProperty], type[LiteralEnumProperty]]
 
@@ -79,3 +84,22 @@ def test_unsupported_type(config: Config, property_class: PropertyClass) -> None
     )
 
     assert isinstance(err, PropertyError)
+
+
+def test_nullable_enum(config):
+    data = oai.Schema(
+        type="string",
+        enum=["a", "b", None],
+        nullable=True,
+    )
+    schemas = Schemas()
+
+    p, _ = EnumProperty.build(
+        data=data, name="prop1", required=True, schemas=schemas, parent_name="parent", config=config
+    )
+
+    assert isinstance(p, UnionProperty)
+    assert len(p.inner_properties) == 2
+    assert isinstance(p.inner_properties[0], NoneProperty)
+    assert isinstance(p.inner_properties[1], EnumProperty)
+    assert p.inner_properties[1].class_info.name == "ParentProp1"
diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py
index 918defcdb..359ded8db 100644
--- a/tests/test_parser/test_properties/test_init.py
+++ b/tests/test_parser/test_properties/test_init.py
@@ -12,6 +12,9 @@
     StringProperty,
     UnionProperty,
 )
+from openapi_python_client.parser.properties.float import FloatProperty
+from openapi_python_client.parser.properties.int import IntProperty
+from openapi_python_client.parser.properties.none import NoneProperty
 from openapi_python_client.parser.properties.protocol import ModelProperty, Value
 from openapi_python_client.parser.properties.schemas import Class
 from openapi_python_client.schema import DataType
@@ -441,14 +444,23 @@ def test_property_from_data_str_enum(self, enum_property_factory, config):
             "ParentAnEnum": prop,
         }
 
+    @pytest.mark.parametrize(
+        "desc,extra_props",
+        [
+            ("3_1_implicit_type", {}),
+            ("3_1_explicit_type", {"type": ["string", "null"]}),
+            ("3_0_implicit_type", {"nullable": True}),
+            ("3_0_explicit_type", {"type": "string", "nullable": True}),
+        ],
+    )
     def test_property_from_data_str_enum_with_null(
-        self, enum_property_factory, union_property_factory, none_property_factory, config
+        self, desc, extra_props, enum_property_factory, union_property_factory, none_property_factory, config
     ):
         from openapi_python_client.parser.properties import Class, Schemas, property_from_data
         from openapi_python_client.schema import Schema
 
         existing = enum_property_factory()
-        data = Schema(title="AnEnum", enum=["A", "B", "C", None], default="B")
+        data = Schema(title="AnEnum", enum=["A", "B", "C", None], default="B", **extra_props)
         name = "my_enum"
         required = True
 
@@ -461,18 +473,19 @@ def test_property_from_data_str_enum_with_null(
         # None / null is removed from enum, and property is now nullable
         assert isinstance(prop, UnionProperty), "Enums with None should be converted to UnionProperties"
         enum_prop = enum_property_factory(
-            name="my_enum_type_1",
+            name=name,
             required=required,
             values={"A": "A", "B": "B", "C": "C"},
             class_info=Class(name=ClassName("ParentAnEnum", ""), module_name=PythonIdentifier("parent_an_enum", "")),
             value_type=str,
             default=Value(python_code="ParentAnEnum.B", raw_value="B"),
         )
-        none_property = none_property_factory(name="my_enum_type_0", required=required)
+        none_property = none_property_factory(name=f"{name}_type_0", required=required)
         assert prop == union_property_factory(
             name=name,
             default=Value(python_code="ParentAnEnum.B", raw_value="B"),
             inner_properties=[none_property, enum_prop],
+            required=required,
         )
         assert schemas != new_schemas, "Provided Schemas was mutated"
         assert new_schemas.classes_by_name == {
@@ -748,6 +761,33 @@ def test_property_from_data_list_of_types(self, config):
 
         assert isinstance(response, UnionProperty)
         assert len(response.inner_properties) == 2
+        assert isinstance(response.inner_properties[0], FloatProperty)
+        assert isinstance(response.inner_properties[1], NoneProperty)
+
+    def test_property_from_data_list_of_types_and_oneof(self, config):
+        from openapi_python_client.parser.properties import Schemas, property_from_data
+
+        name = "union_prop"
+        required = True
+        data = oai.Schema(
+            type=[DataType.NUMBER, DataType.NULL],
+            anyOf=[
+                oai.Schema(type=DataType.NUMBER),
+                oai.Schema(type=DataType.INTEGER),  # this is OK because an integer is also a number
+                oai.Schema(type=DataType.NULL),
+            ],
+        )
+        schemas = Schemas()
+
+        response = property_from_data(
+            name=name, required=required, data=data, schemas=schemas, parent_name="parent", config=config
+        )[0]
+
+        assert isinstance(response, UnionProperty)
+        assert len(response.inner_properties) == 3
+        assert isinstance(response.inner_properties[0], FloatProperty)
+        assert isinstance(response.inner_properties[1], IntProperty)
+        assert isinstance(response.inner_properties[2], NoneProperty)
 
     def test_property_from_data_union_of_one_element(self, model_property_factory, config):
         from openapi_python_client.parser.properties import Schemas, property_from_data
diff --git a/tests/test_parser/test_properties/test_union.py b/tests/test_parser/test_properties/test_union.py
index acbbd06d6..decf6c412 100644
--- a/tests/test_parser/test_properties/test_union.py
+++ b/tests/test_parser/test_properties/test_union.py
@@ -1,8 +1,12 @@
 import openapi_python_client.schema as oai
 from openapi_python_client.parser.errors import ParseError, PropertyError
 from openapi_python_client.parser.properties import Schemas, UnionProperty
+from openapi_python_client.parser.properties.enum_property import EnumProperty
+from openapi_python_client.parser.properties.model_property import ModelProperty
 from openapi_python_client.parser.properties.protocol import Value
+from openapi_python_client.parser.properties.schemas import Class
 from openapi_python_client.schema import DataType, ParameterLocation
+from openapi_python_client.utils import ClassName
 
 
 def test_property_from_data_union(union_property_factory, date_time_property_factory, string_property_factory, config):
@@ -33,6 +37,97 @@ def test_property_from_data_union(union_property_factory, date_time_property_fac
     assert s == Schemas()
 
 
+def test_name_is_preserved_if_union_is_nullable_model(config):
+    from openapi_python_client.parser.properties import Schemas, property_from_data
+
+    parent_name = "parent"
+    name = "prop_1"
+    required = True
+    data = oai.Schema(
+        oneOf=[
+            oai.Schema(type=DataType.OBJECT),
+            oai.Schema(type=DataType.NULL),
+        ],
+    )
+    expected_model_class = Class(name=ClassName("ParentProp1", ""), module_name="parent_prop_1")
+
+    p, s = property_from_data(
+        name=name, required=required, data=data, schemas=Schemas(), parent_name=parent_name, config=config
+    )
+
+    assert isinstance(p, UnionProperty)
+    assert len(p.inner_properties) == 2
+    prop1 = p.inner_properties[0]
+    assert isinstance(prop1, ModelProperty)
+    assert prop1.name == name
+    assert prop1.class_info == expected_model_class
+
+    assert s == Schemas(classes_by_name={expected_model_class.name: prop1}, models_to_process=[prop1])
+
+
+def test_name_is_preserved_if_union_is_nullable_enum(config):
+    from openapi_python_client.parser.properties import Schemas, property_from_data
+
+    parent_name = "parent"
+    name = "prop_1"
+    required = True
+    data = oai.Schema(
+        oneOf=[
+            oai.Schema(type=DataType.INTEGER, enum=[10, 20]),
+            oai.Schema(type=DataType.NULL),
+        ],
+    )
+    expected_enum_class = Class(name=ClassName("ParentProp1", ""), module_name="parent_prop_1")
+
+    p, s = property_from_data(
+        name=name, required=required, data=data, schemas=Schemas(), parent_name=parent_name, config=config
+    )
+
+    assert isinstance(p, UnionProperty)
+    assert len(p.inner_properties) == 2
+    prop1 = p.inner_properties[0]
+    assert isinstance(prop1, EnumProperty)
+    assert prop1.name == name
+    assert prop1.class_info == expected_enum_class
+
+    assert s == Schemas(classes_by_name={expected_enum_class.name: prop1})
+
+
+def test_name_is_preserved_if_union_has_multiple_models_or_enums(config):
+    from openapi_python_client.parser.properties import Schemas, property_from_data
+
+    parent_name = "parent"
+    name = "prop_1"
+    required = True
+    data = oai.Schema(
+        oneOf=[
+            oai.Schema(type=DataType.OBJECT),
+            oai.Schema(type=DataType.INTEGER, enum=[10, 20]),
+        ],
+    )
+    expected_model_class = Class(name=ClassName("ParentProp1Type0", ""), module_name="parent_prop_1_type_0")
+    expected_enum_class = Class(name=ClassName("ParentProp1Type1", ""), module_name="parent_prop_1_type_1")
+
+    p, s = property_from_data(
+        name=name, required=required, data=data, schemas=Schemas(), parent_name=parent_name, config=config
+    )
+
+    assert isinstance(p, UnionProperty)
+    assert len(p.inner_properties) == 2
+    [prop1, prop2] = p.inner_properties
+    assert isinstance(prop1, ModelProperty)
+    assert prop1.name == f"{name}_type_0"
+    assert prop1.class_info == expected_model_class
+    assert isinstance(prop2, EnumProperty)
+    assert prop2.name == f"{name}_type_1"
+    assert prop2.class_info == expected_enum_class
+
+    assert s == Schemas(
+        classes_by_name={expected_model_class.name: prop1, expected_enum_class.name: prop2},
+        models_to_process=[prop1],
+    )
+
+
 def test_build_union_property_invalid_property(config):
     name = "bad_union"
     required = True