mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-22 22:32:23 +00:00
Support bytes in JSON output.
This commit is contained in:
parent
963f9ba94b
commit
96231fab5f
@ -13,16 +13,19 @@ if PY2:
|
|||||||
import six
|
import six
|
||||||
import os, time, sys
|
import os, time, sys
|
||||||
import yaml
|
import yaml
|
||||||
|
import json
|
||||||
|
|
||||||
from twisted.trial import unittest
|
from twisted.trial import unittest
|
||||||
|
|
||||||
from allmydata.util import idlib, mathutil
|
from allmydata.util import idlib, mathutil
|
||||||
from allmydata.util import fileutil
|
from allmydata.util import fileutil
|
||||||
|
from allmydata.util import jsonbytes
|
||||||
from allmydata.util import pollmixin
|
from allmydata.util import pollmixin
|
||||||
from allmydata.util import yamlutil
|
from allmydata.util import yamlutil
|
||||||
from allmydata.util.fileutil import EncryptedTemporaryFile
|
from allmydata.util.fileutil import EncryptedTemporaryFile
|
||||||
from allmydata.test.common_util import ReallyEqualMixin
|
from allmydata.test.common_util import ReallyEqualMixin
|
||||||
|
|
||||||
|
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
long = int
|
long = int
|
||||||
|
|
||||||
@ -469,3 +472,19 @@ class YAML(unittest.TestCase):
|
|||||||
self.assertIsInstance(back[0], str)
|
self.assertIsInstance(back[0], str)
|
||||||
self.assertIsInstance(back[1], str)
|
self.assertIsInstance(back[1], str)
|
||||||
self.assertIsInstance(back[2], str)
|
self.assertIsInstance(back[2], str)
|
||||||
|
|
||||||
|
|
||||||
|
class JSONBytes(unittest.TestCase):
|
||||||
|
"""Tests for BytesJSONEncoder."""
|
||||||
|
|
||||||
|
def test_encode_bytes(self):
|
||||||
|
"""BytesJSONEncoder can encode bytes."""
|
||||||
|
data = {
|
||||||
|
b"hello": [1, b"cd"],
|
||||||
|
}
|
||||||
|
expected = {
|
||||||
|
u"hello": [1, u"cd"],
|
||||||
|
}
|
||||||
|
encoded = jsonbytes.dumps(data)
|
||||||
|
self.assertEqual(json.loads(encoded), expected)
|
||||||
|
self.assertEqual(jsonbytes.loads(encoded), expected)
|
||||||
|
@ -72,6 +72,7 @@ PORTED_MODULES = [
|
|||||||
"allmydata.util.hashutil",
|
"allmydata.util.hashutil",
|
||||||
"allmydata.util.humanreadable",
|
"allmydata.util.humanreadable",
|
||||||
"allmydata.util.iputil",
|
"allmydata.util.iputil",
|
||||||
|
"allmydata.util.jsonbytes",
|
||||||
"allmydata.util.log",
|
"allmydata.util.log",
|
||||||
"allmydata.util.mathutil",
|
"allmydata.util.mathutil",
|
||||||
"allmydata.util.namespace",
|
"allmydata.util.namespace",
|
||||||
|
51
src/allmydata/util/jsonbytes.py
Normal file
51
src/allmydata/util/jsonbytes.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
"""
|
||||||
|
A JSON encoder than can serialize bytes.
|
||||||
|
|
||||||
|
Ported to Python 3.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from __future__ import division
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
from future.utils import PY2
|
||||||
|
if PY2:
|
||||||
|
from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class BytesJSONEncoder(json.JSONEncoder):
|
||||||
|
"""
|
||||||
|
A JSON encoder than can also encode bytes.
|
||||||
|
|
||||||
|
The bytes are assumed to be UTF-8 encoded Unicode strings.
|
||||||
|
"""
|
||||||
|
def default(self, o):
|
||||||
|
if isinstance(o, bytes):
|
||||||
|
return o.decode("utf-8")
|
||||||
|
return json.JSONEncoder.default(self, o)
|
||||||
|
|
||||||
|
|
||||||
|
def dumps(obj, *args, **kwargs):
|
||||||
|
"""Encode to JSON, supporting bytes as keys or values.
|
||||||
|
|
||||||
|
The bytes are assumed to be UTF-8 encoded Unicode strings.
|
||||||
|
"""
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
new_obj = {}
|
||||||
|
for k, v in obj.items():
|
||||||
|
if isinstance(k, bytes):
|
||||||
|
k = k.decode("utf-8")
|
||||||
|
new_obj[k] = v
|
||||||
|
obj = new_obj
|
||||||
|
return json.dumps(obj, cls=BytesJSONEncoder, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
# To make this module drop-in compatible with json module:
|
||||||
|
loads = json.loads
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["dumps", "loads"]
|
@ -1,7 +1,6 @@
|
|||||||
from future.builtins import str
|
from future.builtins import str
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import json
|
|
||||||
|
|
||||||
from twisted.web import (
|
from twisted.web import (
|
||||||
http,
|
http,
|
||||||
@ -32,6 +31,7 @@ from allmydata.interfaces import (
|
|||||||
from allmydata.util import (
|
from allmydata.util import (
|
||||||
base32,
|
base32,
|
||||||
dictutil,
|
dictutil,
|
||||||
|
jsonbytes as json, # Supporting dumping bytes
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user