微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python json 编码器将 Decimal 转换为 null

如何解决Python json 编码器将 Decimal 转换为 null

我正在使用 Flask 和 simplejson 并配置了一个自定义的 json 编码器来将 dicts 转换为 json。

Custon 编码器:

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,decimal.Decimal):
      return (str(o) for o in [o])    
    return super(CustomJSONEncoder,self)._iterencode(o,markers)


def json_encode(data):
  return CustomJSONEncoder().encode(data)

假设我有一个变量 b = [{"os": Decimal('7'),"num": 77777}]

如果我运行 json_encode(b)。这导致 '[{"os": null,"num": 77777}]'。 Decimal 值已转换为 null。

现在我通过仅返回 float(o) 来更改自定义编码器处理小数的方式来解决此问题。虽然这有效,但我想了解编码器的原始版本有什么问题。

我尝试在全局变量 gen 中捕获生成器对象并对其进行迭代。我可以看到值 7 正确出现。

完整的 ipython 控制台日志:

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,markers=None):
    ...:     if isinstance(o,decimal.Decimal):
    ...:       return (str(o) for o in [o])
    ...:     return super(CustomJSONEncoder,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'

问题究竟出在哪里?为什么 Decimal 返回 null ?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。