diff --git a/homeassistant/components/http/view.py b/homeassistant/components/http/view.py index 299a10e9f5a..81c6ea4bcfb 100644 --- a/homeassistant/components/http/view.py +++ b/homeassistant/components/http/view.py @@ -9,7 +9,7 @@ import json import logging from aiohttp import web -from aiohttp.web_exceptions import HTTPUnauthorized +from aiohttp.web_exceptions import HTTPUnauthorized, HTTPInternalServerError import homeassistant.remote as rem from homeassistant.core import is_callback @@ -31,8 +31,12 @@ class HomeAssistantView(object): # pylint: disable=no-self-use def json(self, result, status_code=200, headers=None): """Return a JSON response.""" - msg = json.dumps( - result, sort_keys=True, cls=rem.JSONEncoder).encode('UTF-8') + try: + msg = json.dumps( + result, sort_keys=True, cls=rem.JSONEncoder).encode('UTF-8') + except TypeError as err: + _LOGGER.error('Unable to serialize to JSON: %s\n%s', err, result) + raise HTTPInternalServerError response = web.Response( body=msg, content_type=CONTENT_TYPE_JSON, status=status_code, headers=headers) diff --git a/homeassistant/components/websocket_api.py b/homeassistant/components/websocket_api.py index 47ef2c3eace..1e23ad19897 100644 --- a/homeassistant/components/websocket_api.py +++ b/homeassistant/components/websocket_api.py @@ -240,7 +240,11 @@ class ActiveConnection: if message is None: break self.debug("Sending", message) - await self.wsock.send_json(message, dumps=JSON_DUMP) + try: + await self.wsock.send_json(message, dumps=JSON_DUMP) + except TypeError as err: + _LOGGER.error('Unable to serialize to JSON: %s\n%s', + err, message) @callback def send_message_outside(self, message): diff --git a/homeassistant/remote.py b/homeassistant/remote.py index 566f37a621a..5a33bd58641 100644 --- a/homeassistant/remote.py +++ b/homeassistant/remote.py @@ -123,17 +123,7 @@ class JSONEncoder(json.JSONEncoder): elif hasattr(o, 'as_dict'): return o.as_dict() - try: - return json.JSONEncoder.default(self, o) - except TypeError: - # If the JSON serializer couldn't serialize it - # it might be a generator, convert it to a list - try: - return [self.default(child_obj) - for child_obj in o] - except TypeError: - # Ok, we're lost, cause the original error - return json.JSONEncoder.default(self, o) + return json.JSONEncoder.default(self, o) def validate_api(api): diff --git a/tests/components/http/test_view.py b/tests/components/http/test_view.py new file mode 100644 index 00000000000..ac0e23edd64 --- /dev/null +++ b/tests/components/http/test_view.py @@ -0,0 +1,15 @@ +"""Tests for Home Assistant View.""" +from aiohttp.web_exceptions import HTTPInternalServerError +import pytest + +from homeassistant.components.http.view import HomeAssistantView + + +async def test_invalid_json(caplog): + """Test trying to return invalid JSON.""" + view = HomeAssistantView() + + with pytest.raises(HTTPInternalServerError): + view.json(object) + + assert str(object) in caplog.text