I want to serialize mongoDb's output to actual VALID json in python. I've found several libraries, but none of them seems to both produce valid json and handle incompatible values with null (undefined would be fine also).
Example input:
{
"_id" : ObjectId("57f3e32c71285f85b46d6fb5"),
"rate" : Infinity
"value" : NaN
}
Expected output:
(tried json.dumps and its allow_nan option, but it throws errors and it doesn't help at all)
{
"_id" : { $oid: "57f3e32c71285f85b46d6fb5" },
"rate" : null,
"value" : null
}
Anyone knows a way / library to achieve this ?
As an example, Javascript's JSON does this fine:
Object {_id: "57f3e32c71285f85b46d6fb5", rate: Infinity, value: NaN}
JSON.stringify(tg)
"{"_id":"57f3e32c71285f85b46d6fb5","rate":null,"value":null}"
you can always make your own encoder (I stole this one from https://gist.github.com/pauloalem/6244976 )
import json
class FloatEncoder(json.JSONEncoder):
def __init__(self, nan_str="null", **kwargs):
super(FloatEncoder, self).__init__(**kwargs)
self.nan_str = nan_str
def iterencode(self, o, _one_shot=False):
"""Encode the given object and yield each string
representation as available.
For example::
for chunk in JSONEncoder().iterencode(bigobject):
mysocket.write(chunk)
"""
if self.check_circular:
markers = {}
else:
markers = None
if self.ensure_ascii:
_encoder = json.encoder.encode_basestring_ascii
else:
_encoder = json.encoder.encode_basestring
# if self.encoding != 'utf-8':
# def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
# if isinstance(o, str):
# o = o.decode(_encoding)
# return _orig_encoder(o)
def floatstr(o, allow_nan=self.allow_nan, _repr=json.encoder.encode_basestring,
_inf=json.encoder.INFINITY, _neginf=-json.encoder.INFINITY,
nan_str=self.nan_str):
# Check for specials. Note that this type of test is processor
# and/or platform-specific, so do tests which don't depend on the
# internals.
if o != o:
text = nan_str
elif o == _inf:
text = 'Infinity'
elif o == _neginf:
text = '-Infinity'
else:
return _repr(o)
if not allow_nan:
raise ValueError(
"Out of range float values are not JSON compliant: " +
repr(o))
return text
_iterencode = json.encoder._make_iterencode(
markers, self.default, _encoder, self.indent, floatstr,
self.key_separator, self.item_separator, self.sort_keys,
self.skipkeys, _one_shot)
return _iterencode(o, 0)
d = {"i_will_byte_you_in_the_ass": float("NaN")}
print( json.dumps(d, cls=FloatEncoder) )