mirror of
https://github.com/correl/openapi-core.git
synced 2024-11-24 11:09:54 +00:00
767 lines
21 KiB
Python
767 lines
21 KiB
Python
import datetime
|
|
import uuid
|
|
|
|
from isodate.tzinfo import UTC, FixedOffset
|
|
import pytest
|
|
|
|
from openapi_core.schema.schemas.types import NoValue
|
|
from openapi_core.spec.paths import SpecPath
|
|
from openapi_core.unmarshalling.schemas.enums import UnmarshalContext
|
|
from openapi_core.unmarshalling.schemas.exceptions import (
|
|
InvalidSchemaFormatValue, InvalidSchemaValue, UnmarshalError,
|
|
FormatterNotFoundError,
|
|
)
|
|
from openapi_core.unmarshalling.schemas.factories import (
|
|
SchemaUnmarshallersFactory,
|
|
)
|
|
from openapi_core.unmarshalling.schemas.formatters import Formatter
|
|
from openapi_core.unmarshalling.schemas.util import build_format_checker
|
|
|
|
|
|
@pytest.fixture
|
|
def unmarshaller_factory():
|
|
def create_unmarshaller(schema, custom_formatters=None, context=None):
|
|
custom_formatters = custom_formatters or {}
|
|
format_checker = build_format_checker(**custom_formatters)
|
|
return SchemaUnmarshallersFactory(
|
|
format_checker=format_checker,
|
|
custom_formatters=custom_formatters, context=context).create(
|
|
schema)
|
|
return create_unmarshaller
|
|
|
|
|
|
class TestUnmarshal(object):
|
|
|
|
def test_no_schema(self, unmarshaller_factory):
|
|
schema = None
|
|
value = 'test'
|
|
|
|
with pytest.raises(TypeError):
|
|
unmarshaller_factory(schema).unmarshal(value)
|
|
|
|
def test_schema_type_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'integer',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'test'
|
|
|
|
with pytest.raises(InvalidSchemaFormatValue):
|
|
unmarshaller_factory(schema).unmarshal(value)
|
|
|
|
def test_schema_custom_format_invalid(self, unmarshaller_factory):
|
|
|
|
class CustomFormatter(Formatter):
|
|
def unmarshal(self, value):
|
|
raise ValueError
|
|
formatter = CustomFormatter()
|
|
custom_format = 'custom'
|
|
custom_formatters = {
|
|
custom_format: formatter,
|
|
}
|
|
spec = {
|
|
'type': 'string',
|
|
'format': 'custom',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'test'
|
|
|
|
with pytest.raises(InvalidSchemaFormatValue):
|
|
unmarshaller_factory(
|
|
schema,
|
|
custom_formatters=custom_formatters,
|
|
).unmarshal(value)
|
|
|
|
|
|
class TestSchemaUnmarshallerCall(object):
|
|
|
|
def test_deprecated(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
'deprecated': True,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'test'
|
|
|
|
with pytest.warns(DeprecationWarning):
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == value
|
|
|
|
@pytest.mark.parametrize('schema_type', [
|
|
'boolean', 'array', 'integer', 'number',
|
|
])
|
|
def test_non_string_empty_value(self, schema_type, unmarshaller_factory):
|
|
spec = {
|
|
'type': schema_type,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = ''
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_string_valid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'test'
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == value
|
|
|
|
def test_string_format_uuid_valid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
'format': 'uuid',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = str(uuid.uuid4())
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == uuid.UUID(value)
|
|
|
|
def test_string_format_uuid_uuid_quirks_invalid(
|
|
self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
'format': 'uuid',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = uuid.uuid4()
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_string_format_password(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
'format': 'password',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'password'
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == 'password'
|
|
|
|
def test_string_float_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 1.23
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_string_default(self, unmarshaller_factory):
|
|
default_value = 'default'
|
|
spec = {
|
|
'type': 'string',
|
|
'default': default_value,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = NoValue
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == default_value
|
|
|
|
@pytest.mark.parametrize('default_value', ['default', None])
|
|
def test_string_default_nullable(
|
|
self, default_value, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
'default': default_value,
|
|
'nullable': True,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = NoValue
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == default_value
|
|
|
|
def test_string_format_date(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
'format': 'date',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '2018-01-02'
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == datetime.date(2018, 1, 2)
|
|
|
|
def test_string_format_datetime_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
'format': 'date-time',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '2018-01-02T00:00:00'
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_string_format_datetime_utc(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
'format': 'date-time',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '2018-01-02T00:00:00Z'
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
tzinfo = UTC
|
|
assert result == datetime.datetime(2018, 1, 2, 0, 0, tzinfo=tzinfo)
|
|
|
|
def test_string_format_datetime_tz(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'string',
|
|
'format': 'date-time',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '2020-04-01T12:00:00+02:00'
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
tzinfo = FixedOffset(2)
|
|
assert result == datetime.datetime(2020, 4, 1, 12, 0, 0, tzinfo=tzinfo)
|
|
|
|
def test_string_format_custom(self, unmarshaller_factory):
|
|
formatted = 'x-custom'
|
|
|
|
class CustomFormatter(Formatter):
|
|
def unmarshal(self, value):
|
|
return formatted
|
|
custom_format = 'custom'
|
|
spec = {
|
|
'type': 'string',
|
|
'format': custom_format,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'x'
|
|
formatter = CustomFormatter()
|
|
custom_formatters = {
|
|
custom_format: formatter,
|
|
}
|
|
|
|
result = unmarshaller_factory(
|
|
schema, custom_formatters=custom_formatters)(value)
|
|
|
|
assert result == formatted
|
|
|
|
def test_string_format_custom_value_error(self, unmarshaller_factory):
|
|
|
|
class CustomFormatter(Formatter):
|
|
def unmarshal(self, value):
|
|
raise ValueError
|
|
custom_format = 'custom'
|
|
spec = {
|
|
'type': 'string',
|
|
'format': custom_format,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'x'
|
|
formatter = CustomFormatter()
|
|
custom_formatters = {
|
|
custom_format: formatter,
|
|
}
|
|
|
|
with pytest.raises(InvalidSchemaFormatValue):
|
|
unmarshaller_factory(schema, custom_formatters=custom_formatters)(
|
|
value)
|
|
|
|
def test_string_format_unknown(self, unmarshaller_factory):
|
|
unknown_format = 'unknown'
|
|
spec = {
|
|
'type': 'string',
|
|
'format': unknown_format,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'x'
|
|
|
|
with pytest.raises(FormatterNotFoundError):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_string_format_invalid_value(self, unmarshaller_factory):
|
|
custom_format = 'custom'
|
|
spec = {
|
|
'type': 'string',
|
|
'format': custom_format,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'x'
|
|
|
|
with pytest.raises(
|
|
FormatterNotFoundError,
|
|
message=(
|
|
'Formatter not found for custom format'
|
|
),
|
|
):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_integer_valid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'integer',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 123
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == int(value)
|
|
|
|
def test_integer_string_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'integer',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '123'
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_integer_enum_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'integer',
|
|
'enum': [1, 2, 3],
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '123'
|
|
|
|
with pytest.raises(UnmarshalError):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_integer_enum(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'integer',
|
|
'enum': [1, 2, 3],
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 2
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == int(value)
|
|
|
|
def test_integer_enum_string_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'integer',
|
|
'enum': [1, 2, 3],
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '2'
|
|
|
|
with pytest.raises(UnmarshalError):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_integer_default(self, unmarshaller_factory):
|
|
default_value = 123
|
|
spec = {
|
|
'type': 'integer',
|
|
'default': default_value,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = NoValue
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == default_value
|
|
|
|
def test_integer_default_nullable(self, unmarshaller_factory):
|
|
default_value = 123
|
|
spec = {
|
|
'type': 'integer',
|
|
'default': default_value,
|
|
'nullable': True,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = None
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result is None
|
|
|
|
def test_integer_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'integer',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'abc'
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_array_valid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'array',
|
|
'items': {
|
|
'type': 'integer',
|
|
}
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = [1, 2, 3]
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == value
|
|
|
|
def test_array_null(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'array',
|
|
'items': {
|
|
'type': 'integer',
|
|
}
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = None
|
|
|
|
with pytest.raises(TypeError):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_array_nullable(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'array',
|
|
'items': {
|
|
'type': 'integer',
|
|
},
|
|
'nullable': True,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = None
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result is None
|
|
|
|
def test_array_of_string_string_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'array',
|
|
'items': {
|
|
'type': 'string',
|
|
}
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '123'
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_array_of_integer_string_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'array',
|
|
'items': {
|
|
'type': 'integer',
|
|
}
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '123'
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_boolean_valid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'boolean',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = True
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == value
|
|
|
|
def test_boolean_string_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'boolean',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 'True'
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_number_valid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'number',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 1.23
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == value
|
|
|
|
def test_number_string_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'number',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '1.23'
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_number_int(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'number',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 1
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == 1
|
|
assert type(result) == int
|
|
|
|
def test_number_float(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'number',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 1.2
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == 1.2
|
|
assert type(result) == float
|
|
|
|
def test_number_format_float(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'number',
|
|
'format': 'float',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 1.2
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == 1.2
|
|
|
|
def test_number_format_double(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'number',
|
|
'format': 'double',
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = 1.2
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == 1.2
|
|
|
|
def test_object_nullable(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'object',
|
|
'properties': {
|
|
'foo': {
|
|
'type': 'object',
|
|
'nullable': True,
|
|
}
|
|
},
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = {'foo': None}
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == {'foo': None}
|
|
|
|
def test_schema_any_one_of(self, unmarshaller_factory):
|
|
spec = {
|
|
'oneOf': [
|
|
{
|
|
'type': 'string',
|
|
},
|
|
{
|
|
'type': 'array',
|
|
'items': {
|
|
'type': 'string',
|
|
}
|
|
}
|
|
],
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
assert unmarshaller_factory(schema)(['hello']) == ['hello']
|
|
|
|
def test_schema_any_all_of(self, unmarshaller_factory):
|
|
spec = {
|
|
'allOf': [
|
|
{
|
|
'type': 'array',
|
|
'items': {
|
|
'type': 'string',
|
|
}
|
|
}
|
|
],
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
assert unmarshaller_factory(schema)(['hello']) == ['hello']
|
|
|
|
@pytest.mark.parametrize('value', [
|
|
{
|
|
'somestr': {},
|
|
'someint': 123,
|
|
},
|
|
{
|
|
'somestr': [
|
|
'content1', 'content2'
|
|
],
|
|
'someint': 123,
|
|
},
|
|
{
|
|
'somestr': 123,
|
|
'someint': 123,
|
|
},
|
|
{
|
|
'somestr': 'content',
|
|
'someint': 123,
|
|
'not_in_scheme_prop': 123,
|
|
},
|
|
])
|
|
def test_schema_any_all_of_invalid_properties(
|
|
self, value, unmarshaller_factory):
|
|
spec = {
|
|
'allOf': [
|
|
{
|
|
'type': 'object',
|
|
'required': ['somestr'],
|
|
'properties': {
|
|
'somestr': {
|
|
'type': 'string',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
'type': 'object',
|
|
'required': ['someint'],
|
|
'properties': {
|
|
'someint': {
|
|
'type': 'integer',
|
|
},
|
|
},
|
|
}
|
|
],
|
|
'additionalProperties': False,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(schema)(value)
|
|
|
|
def test_schema_any_all_of_any(self, unmarshaller_factory):
|
|
spec = {
|
|
'allOf': [
|
|
{},
|
|
{
|
|
'type': 'string',
|
|
'format': 'date',
|
|
},
|
|
],
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
value = '2018-01-02'
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
|
|
assert result == datetime.date(2018, 1, 2)
|
|
|
|
def test_schema_any(self, unmarshaller_factory):
|
|
spec = {}
|
|
schema = SpecPath.from_spec(spec)
|
|
assert unmarshaller_factory(schema)('string') == 'string'
|
|
|
|
@pytest.mark.parametrize('value', [
|
|
{'additional': 1},
|
|
{'foo': 'bar', 'bar': 'foo'},
|
|
{'additional': {'bar': 1}},
|
|
])
|
|
@pytest.mark.parametrize('additional_properties', [True, {}])
|
|
def test_schema_free_form_object(
|
|
self, value, additional_properties, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'object',
|
|
'additionalProperties': additional_properties,
|
|
}
|
|
schema = SpecPath.from_spec(spec)
|
|
|
|
result = unmarshaller_factory(schema)(value)
|
|
assert result == value
|
|
|
|
def test_read_only_properties(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'object',
|
|
'required': ['id'],
|
|
'properties': {
|
|
'id': {
|
|
'type': 'integer',
|
|
'readOnly': True,
|
|
}
|
|
},
|
|
}
|
|
obj_schema = SpecPath.from_spec(spec)
|
|
|
|
# readOnly properties may be admitted in a Response context
|
|
result = unmarshaller_factory(
|
|
obj_schema, context=UnmarshalContext.RESPONSE)({"id": 10})
|
|
assert result == {
|
|
'id': 10,
|
|
}
|
|
|
|
def test_read_only_properties_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'object',
|
|
'required': ['id'],
|
|
'properties': {
|
|
'id': {
|
|
'type': 'integer',
|
|
'readOnly': True,
|
|
}
|
|
},
|
|
}
|
|
obj_schema = SpecPath.from_spec(spec)
|
|
|
|
# readOnly properties are not admitted on a Request context
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(
|
|
obj_schema, context=UnmarshalContext.REQUEST)({"id": 10})
|
|
|
|
def test_write_only_properties(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'object',
|
|
'required': ['id'],
|
|
'properties': {
|
|
'id': {
|
|
'type': 'integer',
|
|
'writeOnly': True,
|
|
}
|
|
},
|
|
}
|
|
obj_schema = SpecPath.from_spec(spec)
|
|
|
|
# readOnly properties may be admitted in a Response context
|
|
result = unmarshaller_factory(
|
|
obj_schema, context=UnmarshalContext.REQUEST)({"id": 10})
|
|
assert result == {
|
|
'id': 10,
|
|
}
|
|
|
|
def test_write_only_properties_invalid(self, unmarshaller_factory):
|
|
spec = {
|
|
'type': 'object',
|
|
'required': ['id'],
|
|
'properties': {
|
|
'id': {
|
|
'type': 'integer',
|
|
'writeOnly': True,
|
|
}
|
|
},
|
|
}
|
|
obj_schema = SpecPath.from_spec(spec)
|
|
|
|
# readOnly properties are not admitted on a Request context
|
|
with pytest.raises(InvalidSchemaValue):
|
|
unmarshaller_factory(
|
|
obj_schema, context=UnmarshalContext.RESPONSE)({"id": 10})
|