I have a configuration file in JSON that contains a few variables as strings (always ascii). These strings are decoded to unicode by default but since I have to pass these variables to my Python C Extensions I need them as normal Python strings. At the moment I'm using str(unicode)
to convert the JSON strings but a more elegant and less verbose solution would be much appreciated.
Is there a way to change the default translation from string to unicode with a custom JSONDecoder
or object hook?
Not if you're not willing to lose some speed. If being somewhat slower is OK, you have to consider that using plain json.loads
and recursively converting to str
is probably cheaper and maybe faster.
With all that said, if you do want a loads
that returns strings badly enough to accept going through extending code that wasn't meant to, here's one possible result (mostly extending through copy-n-paste) this was asinine, thanks Lennart for making me see the light (i.e., you just need to extend JSONDecoder and a couple of tricks):
import json
from json import decoder, scanner
from json.scanner import make_scanner
from _json import scanstring as c_scanstring
_CONSTANTS = json.decoder._CONSTANTS
py_make_scanner = scanner.py_make_scanner
# Convert from unicode to str
def str_scanstring(*args, **kwargs):
result = c_scanstring(*args, **kwargs)
return str(result[0]), result[1]
# Little dirty trick here
json.decoder.scanstring = str_scanstring
class StrJSONDecoder(decoder.JSONDecoder):
def __init__(self, encoding=None, object_hook=None, parse_float=None,
parse_int=None, parse_constant=None, strict=True,
object_pairs_hook=None):
self.encoding = encoding
self.object_hook = object_hook
self.object_pairs_hook = object_pairs_hook
self.parse_float = parse_float or float
self.parse_int = parse_int or int
self.parse_constant = parse_constant or _CONSTANTS.__getitem__
self.strict = strict
self.parse_object = decoder.JSONObject
self.parse_array = decoder.JSONArray
self.parse_string = str_scanstring
self.scan_once = py_make_scanner(self)
# And another little dirty trick there
_default_decoder = StrJSONDecoder(encoding=None, object_hook=None,
object_pairs_hook=None)
json._default_decoder = _default_decoder
j = {1:'2', 1.1:[1,2,3], u'test': {12:12, 13:'o'}}
print json.loads(json.dumps(j))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With