diff --git a/pygeoapi/util.py b/pygeoapi/util.py index b60e187a08..2accb96c49 100644 --- a/pygeoapi/util.py +++ b/pygeoapi/util.py @@ -423,7 +423,7 @@ def json_serial(obj: Any) -> str: return obj.decode('utf-8') except UnicodeDecodeError: LOGGER.debug('Returning as base64 encoded JSON object') - return base64.b64encode(obj) + return base64.b64encode(obj).decode('ascii') elif isinstance(obj, Decimal): return float(obj) elif type(obj).__name__ in ['int32', 'int64']: diff --git a/tests/other/test_util.py b/tests/other/test_util.py index 7cb321019d..e857e6dad3 100644 --- a/tests/other/test_util.py +++ b/tests/other/test_util.py @@ -166,6 +166,20 @@ def test_json_serial(): d = uuid.UUID('12345678-1234-5678-1234-567812345678') assert util.json_serial(d) == '12345678-1234-5678-1234-567812345678' + # Valid UTF-8 bytes round-trip as a plain string + assert util.json_serial(b'hello') == 'hello' + + # Non-UTF-8 bytes must produce a base64 *str* (not bytes), so that the + # result can be serialised to JSON without a TypeError. + raw = b'\x80\x81\x82' + result = util.json_serial(raw) + assert isinstance(result, str), "json_serial must return str, not bytes" + import base64 as _b64 + assert result == _b64.b64encode(raw).decode('ascii') + import json as _json + # Must be embeddable in a JSON document without raising + _json.dumps({'data': result}) + with pytest.raises(TypeError): util.json_serial('foo')