Response JSON text as array fix

This commit is contained in:
p1c2u 2018-04-23 19:50:29 +01:00
parent 4fc02af09c
commit 0350562b54
5 changed files with 92 additions and 4 deletions

View file

@ -1,9 +1,17 @@
"""OpenAPI core mediaTypes module""" """OpenAPI core mediaTypes module"""
from collections import defaultdict
from json import loads
from six import iteritems from six import iteritems
from openapi_core.exceptions import InvalidValueType, InvalidMediaTypeValue from openapi_core.exceptions import InvalidValueType, InvalidMediaTypeValue
MEDIA_TYPE_DESERIALIZERS = {
'application/json': loads,
}
class MediaType(object): class MediaType(object):
"""Represents an OpenAPI MediaType.""" """Represents an OpenAPI MediaType."""
@ -11,12 +19,29 @@ class MediaType(object):
self.mimetype = mimetype self.mimetype = mimetype
self.schema = schema self.schema = schema
def get_deserializer_mapping(self):
mapping = MEDIA_TYPE_DESERIALIZERS.copy()
return defaultdict(lambda: lambda x: x, mapping)
def get_dererializer(self):
mapping = self.get_deserializer_mapping()
return mapping[self.mimetype]
def deserialize(self, value):
deserializer = self.get_dererializer()
return deserializer(value)
def unmarshal(self, value): def unmarshal(self, value):
if not self.schema: if not self.schema:
return value return value
try: try:
return self.schema.unmarshal(value) deserialized = self.deserialize(value)
except ValueError as exc:
raise InvalidMediaTypeValue(str(exc))
try:
return self.schema.unmarshal(deserialized)
except InvalidValueType as exc: except InvalidValueType as exc:
raise InvalidMediaTypeValue(str(exc)) raise InvalidMediaTypeValue(str(exc))

View file

@ -6,7 +6,6 @@ import warnings
from distutils.util import strtobool from distutils.util import strtobool
from functools import lru_cache from functools import lru_cache
from json import loads
from six import iteritems from six import iteritems
from openapi_core.enums import SchemaType, SchemaFormat from openapi_core.enums import SchemaType, SchemaFormat
@ -126,8 +125,8 @@ class Schema(object):
return list(map(self.items.unmarshal, value)) return list(map(self.items.unmarshal, value))
def _unmarshal_object(self, value): def _unmarshal_object(self, value):
if isinstance(value, (str, bytes)): if not isinstance(value, (dict, )):
value = loads(value) raise InvalidValueType("Value of {0} not an object".format(value))
all_properties = self.get_all_properties() all_properties = self.get_all_properties()
all_required_properties = self.get_all_required_properties() all_required_properties = self.get_all_required_properties()

View file

@ -108,6 +108,21 @@ paths:
$ref: "#/components/schemas/PetData" $ref: "#/components/schemas/PetData"
default: default:
$ref: "#/components/responses/ErrorResponse" $ref: "#/components/responses/ErrorResponse"
/tags:
get:
summary: List all tags
operationId: listTags
tags:
- tags
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/TagList"
default:
$ref: "#/components/responses/ErrorResponse"
components: components:
schemas: schemas:
Address: Address:
@ -186,6 +201,10 @@ components:
properties: properties:
data: data:
$ref: "#/components/schemas/Pet" $ref: "#/components/schemas/Pet"
TagList:
type: array
items:
$ref: "#/components/schemas/Tag"
Error: Error:
type: object type: object
required: required:

View file

@ -655,3 +655,27 @@ class TestPetstore(object):
assert response_result.errors == [] assert response_result.errors == []
assert response_result.data == data_json assert response_result.data == data_json
def test_get_tags(self, spec, response_validator):
host_url = 'http://petstore.swagger.io/v1'
path_pattern = '/v1/tags'
request = MockRequest(
host_url, 'GET', '/tags',
path_pattern=path_pattern,
)
parameters = request.get_parameters(spec)
body = request.get_body(spec)
assert parameters == {}
assert body is None
data_json = []
data = json.dumps(data_json)
response = MockResponse(data)
response_result = response_validator.validate(request, response)
assert response_result.errors == []
assert response_result.data == data_json

View file

@ -4,6 +4,7 @@ import pytest
from openapi_core.exceptions import ( from openapi_core.exceptions import (
InvalidServer, InvalidOperation, MissingParameter, InvalidServer, InvalidOperation, MissingParameter,
MissingBody, InvalidContentType, InvalidResponse, InvalidMediaTypeValue, MissingBody, InvalidContentType, InvalidResponse, InvalidMediaTypeValue,
InvalidValue,
) )
from openapi_core.shortcuts import create_spec from openapi_core.shortcuts import create_spec
from openapi_core.validators import RequestValidator, ResponseValidator from openapi_core.validators import RequestValidator, ResponseValidator
@ -239,6 +240,26 @@ class TestResponseValidator(object):
assert result.data is None assert result.data is None
assert result.headers == {} assert result.headers == {}
def test_invalid_value(self, validator):
request = MockRequest(self.host_url, 'get', '/v1/tags')
response_json = {
'data': [
{
'id': 1,
'name': 'Sparky'
},
],
}
response_data = json.dumps(response_json)
response = MockResponse(response_data)
result = validator.validate(request, response)
assert len(result.errors) == 1
assert type(result.errors[0]) == InvalidValue
assert result.data is None
assert result.headers == {}
def test_get_pets(self, validator): def test_get_pets(self, validator):
request = MockRequest(self.host_url, 'get', '/v1/pets') request = MockRequest(self.host_url, 'get', '/v1/pets')
response_json = { response_json = {