I am using flask and simplejson and have configured a custom json encoder to convert dicts to json.
Custon Encoder:
gen = []
class CustomJSONEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, datetime):
return o.strftime('%Y-%m-%d %H:%M:%S')
if isinstance(o, date):
return o.strftime('%Y-%m-%d')
if isinstance(o, np.int64):
return int(o)
if isinstance(o, decimal.Decimal):
a = (str(o) for o in [o])
gen.append(a)
return a
def _iterencode(self, o, markers=None):
if isinstance(o, np.int64):
return int(o)
if isinstance(o, decimal.Decimal):
return (str(o) for o in [o])
return super(CustomJSONEncoder, self)._iterencode(o, markers)
def json_encode(data):
return CustomJSONEncoder().encode(data)
Suppose I have a variable as b = [{"os": Decimal('7'), "num": 77777}]
.
If I run json_encode(b)
. This results in '[{"os": null, "num": 77777}]'
. The Decimal value got converted to a null.
Now I have fixed this by changing the way the custom encoder handles Decimals by just returning a float(o)
. While this works, I want to understand whats wrong with the original version of the encoder.
I have tried capturing the generator object in a global variable gen
and iterated over it. I can see the value 7 coming correctly.
Full ipython console log:
In [93]: bb
Out[93]: [{'os': Decimal('7'), 'num': 77777}]
In [94]: gen = []
...: class CustomJSONEncoder(json.JSONEncoder):
...:
...: def default(self, o):
...: if isinstance(o, datetime):
...: return o.strftime('%Y-%m-%d %H:%M:%S')
...: if isinstance(o, date):
...: return o.strftime('%Y-%m-%d')
...: if isinstance(o, np.int64):
...: return int(o)
...: if isinstance(o, decimal.Decimal):
...: a = (str(o) for o in [o])
...: gen.append(a)
...: return a
...:
...:
...: def _iterencode(self, o, markers=None):
...: if isinstance(o, np.int64):
...: return int(o)
...: if isinstance(o, decimal.Decimal):
...: return (str(o) for o in [o])
...: return super(CustomJSONEncoder, self)._iterencode(o, markers)
...:
...:
...: def json_encode(data):
...: return CustomJSONEncoder().encode(data)
...:
In [95]: json_encode(bb)
Out[95]: '[{"os": null, "num": 77777}]'
In [96]: gen[0]
Out[96]: <generator object CustomJSONEncoder.default.<locals>.<genexpr> at 0x7f45cdb37990>
In [97]: next(gen[0])
Out[97]: '7'
Where exactly is the issue ? Why is null being returned for Decimal ?