diff --git a/src/wuttaweb/util.py b/src/wuttaweb/util.py index c0069d4..0697f03 100644 --- a/src/wuttaweb/util.py +++ b/src/wuttaweb/util.py @@ -24,6 +24,7 @@ Web Utilities """ +import decimal import importlib import json import logging @@ -525,17 +526,28 @@ def make_json_safe(value, key=None, warn=True): if value is colander.null: return None - # recursively convert dict - if isinstance(value, dict): + elif isinstance(value, dict): + # recursively convert dict parent = dict(value) for key, value in parent.items(): parent[key] = make_json_safe(value, key=key, warn=warn) value = parent - # convert UUID to str - if isinstance(value, _uuid.UUID): + elif isinstance(value, list): + # recursively convert list + parent = list(value) + for i, value in enumerate(parent): + parent[i] = make_json_safe(value, key=key, warn=warn) + value = parent + + elif isinstance(value, _uuid.UUID): + # convert UUID to str value = value.hex + elif isinstance(value, decimal.Decimal): + # convert decimal to float + value = float(value) + # ensure JSON-compatibility, warn if problems try: json.dumps(value) diff --git a/tests/test_util.py b/tests/test_util.py index 21de3a4..6946d65 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,5 +1,6 @@ # -*- coding: utf-8; -*- +import decimal import json import uuid as _uuid from unittest import TestCase @@ -570,6 +571,12 @@ class TestMakeJsonSafe(TestCase): value = mod.make_json_safe(uuid) self.assertEqual(value, uuid.hex) + def test_decimal(self): + value = decimal.Decimal('42.42') + self.assertNotEqual(value, 42.42) + result = mod.make_json_safe(value) + self.assertEqual(result, 42.42) + def test_dict(self): model = self.app.model person = model.Person(full_name="Betty Boop") @@ -585,3 +592,21 @@ class TestMakeJsonSafe(TestCase): 'foo': 'bar', 'person': "Betty Boop", }) + + def test_list(self): + model = self.app.model + person = model.Person(full_name="Betty Boop") + + data = [ + 'foo', + 'bar', + person, + ] + + self.assertRaises(TypeError, json.dumps, data) + value = mod.make_json_safe(data) + self.assertEqual(value, [ + 'foo', + 'bar', + "Betty Boop", + ])