Merge pull request #29 from p1c2u/fix/response-json-array-fix

Response JSON text as array fix
This commit is contained in:
A 2018-04-23 23:02:00 +01:00 committed by GitHub
commit 64af4d019a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 4 deletions

View file

@ -1,9 +1,17 @@
"""OpenAPI core mediaTypes module"""
from collections import defaultdict
from json import loads
from six import iteritems
from openapi_core.exceptions import InvalidValueType, InvalidMediaTypeValue
MEDIA_TYPE_DESERIALIZERS = {
'application/json': loads,
}
class MediaType(object):
"""Represents an OpenAPI MediaType."""
@ -11,12 +19,29 @@ class MediaType(object):
self.mimetype = mimetype
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):
if not self.schema:
return value
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:
raise InvalidMediaTypeValue(str(exc))

View file

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

View file

@ -108,6 +108,21 @@ paths:
$ref: "#/components/schemas/PetData"
default:
$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:
schemas:
Address:
@ -186,6 +201,10 @@ components:
properties:
data:
$ref: "#/components/schemas/Pet"
TagList:
type: array
items:
$ref: "#/components/schemas/Tag"
Error:
type: object
required:

View file

@ -655,3 +655,27 @@ class TestPetstore(object):
assert response_result.errors == []
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 (
InvalidServer, InvalidOperation, MissingParameter,
MissingBody, InvalidContentType, InvalidResponse, InvalidMediaTypeValue,
InvalidValue,
)
from openapi_core.shortcuts import create_spec
from openapi_core.validators import RequestValidator, ResponseValidator
@ -239,6 +240,26 @@ class TestResponseValidator(object):
assert result.data is None
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):
request = MockRequest(self.host_url, 'get', '/v1/pets')
response_json = {