diff --git a/src/apispec/ext/marshmallow/field_converter.py b/src/apispec/ext/marshmallow/field_converter.py index 3b837b44..9016e5f5 100644 --- a/src/apispec/ext/marshmallow/field_converter.py +++ b/src/apispec/ext/marshmallow/field_converter.py @@ -318,7 +318,7 @@ def field2nullable(self, field: marshmallow.fields.Field, ret) -> dict: attributes["anyOf"] = [{"$ref": ret.pop("$ref")}, {"type": "null"}] elif "allOf" in ret: attributes["anyOf"] = [*ret.pop("allOf"), {"type": "null"}] - else: + elif "type" in ret: attributes["type"] = [*make_type_list(ret.get("type")), "null"] return attributes diff --git a/tests/test_ext_marshmallow_field.py b/tests/test_ext_marshmallow_field.py index 36d864c4..a24f0a3f 100644 --- a/tests/test_ext_marshmallow_field.py +++ b/tests/test_ext_marshmallow_field.py @@ -199,6 +199,20 @@ def test_field_with_allow_none(spec_fixture): assert res["type"] == ["string", "null"] +@pytest.mark.parametrize("spec_fixture", ("2.0", "3.0.0", "3.1.0"), indirect=True) +@pytest.mark.parametrize("field_class", [fields.Field, fields.Raw]) +def test_nullable_field_with_no_type(spec_fixture, field_class): + field = field_class(allow_none=True) + res = spec_fixture.openapi.field2property(field) + if spec_fixture.openapi.openapi_version.major < 3: + assert res["x-nullable"] is True + elif spec_fixture.openapi.openapi_version.minor < 1: + assert res["nullable"] is True + else: + assert "nullable" not in res + assert "type" not in res + + @pytest.mark.parametrize("spec_fixture", ("2.0", "3.0.0", "3.1.0"), indirect=True) def test_nested_nullable(spec_fixture): class Child(Schema):