diff --git a/bravado_core/schema.py b/bravado_core/schema.py index 884abe9b..0d826463 100644 --- a/bravado_core/schema.py +++ b/bravado_core/schema.py @@ -118,11 +118,15 @@ def handle_null_value(swagger_spec, schema_object_spec): :param swagger_spec: :class:`bravado_core.spec.Spec` :param schema_object_spec: dict - :return: None if the spec is nullable - :raises: SwaggerMappingError if the spec is not nullable + :return: The default if there is a default value, None if the spec is nullable + :raises: SwaggerMappingError if the spec is not nullable and no default exists """ + if has_default(swagger_spec, schema_object_spec): + return get_default(swagger_spec, schema_object_spec) + if is_prop_nullable(swagger_spec, schema_object_spec): return None + raise SwaggerMappingError( 'Spec {0} is a required value'.format(schema_object_spec)) diff --git a/bravado_core/unmarshal.py b/bravado_core/unmarshal.py index 26a074f6..6f1c5038 100644 --- a/bravado_core/unmarshal.py +++ b/bravado_core/unmarshal.py @@ -2,6 +2,7 @@ from six import iteritems from bravado_core import formatter +from bravado_core import schema from bravado_core.exception import SwaggerMappingError from bravado_core.model import is_model, MODEL_MARKER from bravado_core.schema import collapsed_properties @@ -128,7 +129,10 @@ def unmarshal_object(swagger_spec, object_spec, object_value): prop_spec = get_spec_for_prop( swagger_spec, object_spec, object_value, k) if v is None and k not in required_fields: - result[k] = None + if schema.has_default(swagger_spec, prop_spec): + result[k] = schema.get_default(swagger_spec, prop_spec) + else: + result[k] = None elif prop_spec: result[k] = unmarshal_schema_object(swagger_spec, prop_spec, v) else: diff --git a/tests/schema/handle_null_value_test.py b/tests/schema/handle_null_value_test.py new file mode 100644 index 00000000..51f4955b --- /dev/null +++ b/tests/schema/handle_null_value_test.py @@ -0,0 +1,31 @@ +import pytest + +from bravado_core.exception import SwaggerMappingError +from bravado_core.schema import handle_null_value + + +def test_default(empty_swagger_spec): + spec = { + 'type': 'integer', + 'default': 42 + } + + assert 42 == handle_null_value(empty_swagger_spec, spec) + + +def test_nullable(empty_swagger_spec): + spec = { + 'type': 'integer', + 'x-nullable': True, + } + + assert None is handle_null_value(empty_swagger_spec, spec) + + +def test_raise(empty_swagger_spec): + spec = { + 'type': 'integer', + } + + with pytest.raises(SwaggerMappingError): + handle_null_value(empty_swagger_spec, spec) diff --git a/tests/unmarshal/unmarshal_object_test.py b/tests/unmarshal/unmarshal_object_test.py index 2bbf8fea..900d2f29 100644 --- a/tests/unmarshal/unmarshal_object_test.py +++ b/tests/unmarshal/unmarshal_object_test.py @@ -23,7 +23,9 @@ def address_spec(): 'enum': [ 'Street', 'Avenue', - 'Boulevard'] + 'Boulevard', + ], + 'default': 'Street', } } } @@ -95,11 +97,19 @@ def address(): } -def test_with_properties(empty_swagger_spec, address_spec, address): +@pytest.mark.parametrize( + 'street_type, expected_street_type', + ( + ('Avenue', 'Avenue'), + (None, 'Street'), # make sure the default works + ) +) +def test_with_properties(empty_swagger_spec, address_spec, address, street_type, expected_street_type): + address['street_type'] = street_type expected_address = { 'number': 1600, 'street_name': u'Ümlaut', - 'street_type': 'Avenue' + 'street_type': expected_street_type, } result = unmarshal_object(empty_swagger_spec, address_spec, address) assert expected_address == result diff --git a/tests/unmarshal/unmarshal_primitive_test.py b/tests/unmarshal/unmarshal_primitive_test.py index 1c2b624c..1bb6dcba 100644 --- a/tests/unmarshal/unmarshal_primitive_test.py +++ b/tests/unmarshal/unmarshal_primitive_test.py @@ -19,7 +19,7 @@ def test_string(minimal_swagger_spec): minimal_swagger_spec, string_spec, u'Ümlaut') -def test_booean(minimal_swagger_spec): +def test_boolean(minimal_swagger_spec): boolean_spec = {'type': 'boolean'} result = unmarshal_primitive(minimal_swagger_spec, boolean_spec, True) assert isinstance(result, bool) @@ -67,6 +67,15 @@ def test_required_failure(minimal_swagger_spec): assert 'is a required value' in str(excinfo.value) +def test_default(minimal_swagger_spec): + integer_spec = { + 'type': 'integer', + 'default': 42, + } + + assert 42 == unmarshal_primitive(minimal_swagger_spec, integer_spec, None) + + def test_ref(minimal_swagger_dict): minimal_swagger_dict['definitions']['SpecialInteger'] = {'type': 'integer'} special_integer_spec = {'$ref': '#/definitions/SpecialInteger'}