Skip to content

Commit

Permalink
Merge 26d7d51 into 21e290f
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelcaricio committed Mar 29, 2016
2 parents 21e290f + 26d7d51 commit 0aec18a
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 2 deletions.
3 changes: 3 additions & 0 deletions connexion/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .problem import problem
from .api import Api
from connexion.resolver import Resolver
from connexion.decorators.produces import JSONEncoder as ConnexionJSONEncoder

logger = logging.getLogger('connexion.app')

Expand Down Expand Up @@ -53,6 +54,8 @@ def __init__(self, import_name, port=None, specification_dir='',
"""
self.app = flask.Flask(import_name)

self.app.json_encoder = ConnexionJSONEncoder

# we get our application root path from flask to avoid duplicating logic
self.root_path = pathlib.Path(self.app.root_path)
logger.debug('Root Path: %s', self.root_path)
Expand Down
4 changes: 2 additions & 2 deletions connexion/decorators/produces.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
# Decorators to change the return type of endpoints
import datetime
import flask
from flask import json
import functools
import json
import logging
from .decorator import BaseDecorator
from ..utils import is_flask_response
Expand Down Expand Up @@ -124,7 +124,7 @@ def wrapper(*args, **kwargs):
logger.debug('Endpoint returned an empty response (204)', extra={'url': url, 'mimetype': self.mimetype})
return '', 204, headers

data = json.dumps(data, indent=2, cls=JSONEncoder)
data = json.dumps(data, indent=2)
response = flask.current_app.response_class(data, mimetype=self.mimetype) # type: flask.Response
response = self.process_headers(response, headers)

Expand Down
6 changes: 6 additions & 0 deletions connexion/decorators/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"""

# Decorators to change the return type of endpoints
from flask import json
import functools
import logging
from ..exceptions import NonConformingResponseBody, NonConformingResponseHeaders
Expand Down Expand Up @@ -51,6 +52,11 @@ def validate_response(self, data, status_code, headers):
schema = response_definition.get("schema")
v = ResponseBodyValidator(schema)
try:
# For cases of custom encoders, we need to encode and decode to
# transform to the actual types that are going to be returned.
data = json.dumps(data)
data = json.loads(data)

v.validate_schema(data)
except ValidationError as e:
raise NonConformingResponseBody(message=str(e))
Expand Down
8 changes: 8 additions & 0 deletions docs/response.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ for you and set the right content type in the HTTP header.
If the endpoint produces a single non JSON mimetype then Connexion will
automatically set the right content type in the HTTP header.

Customizing JSON encoder
^^^^^^^^^^^^^^^^^^^^^^^^

Connexion allows you to customize the `JSONEncoder` class in the Flask app
instance `json_encoder` (`connexion.App:app`). If you wanna reuse the
Connexion's date-time sezialization, inherit your custom encoder from
`connexion.decorators.produces.JSONEncoder`.

Returning status codes
----------------------
There are two ways of returning a specific status code.
Expand Down
20 changes: 20 additions & 0 deletions tests/api/test_responses.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import json

from connexion.decorators.produces import JSONEncoder


def test_app(simple_app):
assert simple_app.port == 5001
Expand Down Expand Up @@ -107,3 +109,21 @@ def test_default_object_body(simple_app):
assert resp.status_code == 200
response = json.loads(resp.data.decode())
assert response == 1


def test_custom_encoder(simple_app):

class CustomEncoder(JSONEncoder):
def default(self, o):
if o.__class__.__name__ == 'DummyClass':
return "cool result"
return JSONEncoder.default(self, o)

flask_app = simple_app.app
flask_app.json_encoder = CustomEncoder
app_client = flask_app.test_client()

resp = app_client.get('/v1.0/custom-json-response')
assert resp.status_code == 200
response = json.loads(resp.data.decode())
assert response['theResult'] == 'cool result'
6 changes: 6 additions & 0 deletions tests/fakeapi/hello.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env python3

from decimal import Decimal

from connexion import problem, request
from connexion import NoContent
from flask import redirect
Expand Down Expand Up @@ -289,3 +291,7 @@ def test_array_in_path(names):

def test_global_response_definition():
return ['general', 'list'], 200


def test_custom_json_response():
return {'theResult': DummyClass()}, 200
14 changes: 14 additions & 0 deletions tests/fixtures/simple/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,20 @@ paths:
items:
type: string

/custom-json-response:
get:
operationId: fakeapi.hello.test_custom_json_response
produces:
- application/json
responses:
200:
description: OK
schema:
type: object
properties:
theResult:
type: string
description: the number we wanna test

definitions:
new_stack:
Expand Down

0 comments on commit 0aec18a

Please sign in to comment.