• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

2022-07-13 Python Object of type float32 is not JSON serializable

武飞扬头像
颈椎以上瘫痪
帮助1

背景

Python 3.7.6中使用json.dumps(result)对数据转JSON数据出现错误:TypeError: Object of type float32 is not JSON serializable

  1.  
    print("result", result)
  2.  
    dumps = json.dumps(result)
  3.  
    print("dumps", dumps)

打印result的数据如下:

[{'index': 0, 'location': {'ltx': 139, 'lty': 161, 'rbx': 1684, 'rby': 778}, 'label': 'plane', 'confidence': 0.9631122946739197, 'ocr': [{'index': 0, 'label': '120', 'score': 0.8265708088874817, 'location': {'lt': [396.0, 434.0], 'rt': [457.0, 422.0], 'rb': [464.0, 459.0], 'lb': [403.0, 471.0]}}]}]

使用JSON工具转成JSON如下:

  1.  
    [
  2.  
    {
  3.  
    "confidence": 0.9631122946739197,
  4.  
    "index": 0,
  5.  
    "label": "plane",
  6.  
    "location": {
  7.  
    "ltx": 139,
  8.  
    "lty": 161,
  9.  
    "rbx": 1684,
  10.  
    "rby": 778
  11.  
    },
  12.  
    "ocr": [
  13.  
    {
  14.  
    "index": 0,
  15.  
    "label": "120",
  16.  
    "location": {
  17.  
    "lb": [
  18.  
    403.0,
  19.  
    471.0
  20.  
    ],
  21.  
    "lt": [
  22.  
    396.0,
  23.  
    434.0
  24.  
    ],
  25.  
    "rb": [
  26.  
    464.0,
  27.  
    459.0
  28.  
    ],
  29.  
    "rt": [
  30.  
    457.0,
  31.  
    422.0
  32.  
    ]
  33.  
    },
  34.  
    "score": 0.8265708088874817
  35.  
    }
  36.  
    ]
  37.  
    }
  38.  
    ]
学新通

转换过程出现错误,所以后面的就没打印

原因

数据中存在的float32数据是numpy格式的数据,Python内置的float类型可以写入JSON中,但是numpy的float32类型数据不能写入JSON,所以应将numpy.float32类型数据转成Python.float类型数据

解决过程

查看网友的解决方案,有一个说在函数中使用str()函数将result转成字符串:

  1.  
    print("result", result)
  2.  
    dumps = json.dumps(str(result))
  3.  
    print("dumps", dumps)

这样代码确实可以运行,但是转换的结果却是整个字符串:

"[{'index': 0, 'location': {'ltx': 139, 'lty': 161, 'rbx': 1684, 'rby': 778}, 'label': 'plane', 'confidence': 0.9631122946739197, 'ocr': [{'index': 0, 'label': '120', 'score': 0.8265708088874817, 'location': {'lt': [396.0, 434.0], 'rt': [457.0, 422.0], 'rb': [464.0, 459.0], 'lb': [403.0, 471.0]}}]}]"

这种字符串在JSON数据2头加上了引号,把引号去掉确实是可以用,但是这种做法显得太low了,因此重新找其他办法

解决方案

作为一个程序员,上文的解决过程让我心里老难受了,虽然可以很快的应付过去,但是心里总过意不去,因此花了几个小时专门来研究了一下这个问题。

思路很简单,就是将numpy不能写到JSON中的数据类型转换成Python内置数据类型就行,比如笔者这里的数据类型是numpy.float32,很显然我需要将它转为python.float。

那么首先就是要确定numpy.float32能否转换为python.float,这个很容易验证,定义一个numpy.float32数据,然后使用python语法float(numpy.float32)做类型转换就可以了,并且通过下文代码可以发现,这2种数据类型是可以互相转换的。

但是有个问题就是这里测试的float数据很简单,如果出现精度很高的数据不知道会不会出现精度损失的问题,这个问题只是想让大家不要忽略这个问题,具体的操作还是得看业务,比如笔者这里的业务数据精度要求没有这么高,即使有精度损失也是可以忽略的。

  1.  
    import numpy as np
  2.  
     
  3.  
    p1 = 0.1
  4.  
    print(type(p1))
  5.  
     
  6.  
    p2 = np.float32(p1)
  7.  
    print(type(p2))
  8.  
     
  9.  
    p3 = float(p2)
  10.  
    print(type(p3))

然后就是将业务中的数据进行转换了,笔者写了一个工具类,用来做这个操作。这个类基于笔者的数据内容解析了3种数据类型,numpy.float32、list、dict。很显然够用了,大家如果使用到这个类,可以根据自己的数据类型进行扩展。

  1.  
    import numpy as np
  2.  
     
  3.  
    # 对numpy的数据类型进行转换
  4.  
    # 场景:numpy.float32类型不能写入JSON,需要转成Python的float类型
  5.  
    def convertNumpyDataType(data):
  6.  
    if type(data) is list:
  7.  
    return convertList(data)
  8.  
    elif type(data) is dict:
  9.  
    return convertDict(data)
  10.  
    elif type(data) is np.float32:
  11.  
    return convertFloat32(data)
  12.  
    return data
  13.  
     
  14.  
    def convertList(data):
  15.  
    if type(data) is not list:
  16.  
    return data
  17.  
     
  18.  
    temp = []
  19.  
    for obj in data:
  20.  
    temp.append(convertNumpyDataType(obj))
  21.  
     
  22.  
    return temp
  23.  
     
  24.  
    def convertDict(data):
  25.  
    temp = data.copy()
  26.  
    if type(data) is not dict:
  27.  
    return temp
  28.  
     
  29.  
    for key in data.keys():
  30.  
    obj = data.get(key)
  31.  
    temp.__setitem__(key, convertNumpyDataType(obj))
  32.  
     
  33.  
    return temp
  34.  
     
  35.  
    def convertFloat32(data):
  36.  
    return float(data)
学新通

使用场景

在做图像处理后得到数据结果,是一个list,需要将数据转JSON,因此出现本文问题,所以在转之前先将数据类型进行转换

  1.  
    result = detectionAndOcr(img)
  2.  
    print("result:",result)
  3.  
    result = NumpyDataTypeConvert.convertNumpyDataType(result)
  4.  
    print("result:",result)
  5.  
    dumps = json.dumps(result)
  6.  
    print("dumps:",dumps)

这3个打印的内容如下:

  1.  
    result: [{'index': 0, 'location': {'lt': {'x': 139, 'y': 161}, 'rb': {'x': 1684, 'y': 778}}, 'label': 'plane', 'confidence': 0.9631122946739197, 'ocr': [{'index': 0, 'label': '120', 'confidence': 0.8265708088874817, 'location': {'lt': {'x': 396.0, 'y': 434.0}, 'rt': {'x': 457.0, 'y': 422.0}, 'rb': {'x': 464.0, 'y': 459.0}, 'lb': {'x': 403.0, 'y': 471.0}}}]}]
  2.  
    result: [{'index': 0, 'location': {'lt': {'x': 139, 'y': 161}, 'rb': {'x': 1684, 'y': 778}}, 'label': 'plane', 'confidence': 0.9631122946739197, 'ocr': [{'index': 0, 'label': '120', 'confidence': 0.8265708088874817, 'location': {'lt': {'x': 396.0, 'y': 434.0}, 'rt': {'x': 457.0, 'y': 422.0}, 'rb': {'x': 464.0, 'y': 459.0}, 'lb': {'x': 403.0, 'y': 471.0}}}]}]
  3.  
    dumps: [{"index": 0, "location": {"lt": {"x": 139, "y": 161}, "rb": {"x": 1684, "y": 778}}, "label": "plane", "confidence": 0.9631122946739197, "ocr": [{"index": 0, "label": "120", "confidence": 0.8265708088874817, "location": {"lt": {"x": 396.0, "y": 434.0}, "rt": {"x": 457.0, "y": 422.0}, "rb": {"x": 464.0, "y": 459.0}, "lb": {"x": 403.0, "y": 471.0}}}]}]

最后的结果能看出来数据转换是可以行的。

  1.  
    [
  2.  
    {
  3.  
    "confidence": 0.9631122946739197,
  4.  
    "index": 0,
  5.  
    "label": "plane",
  6.  
    "location": {
  7.  
    "lt": {
  8.  
    "x": 139,
  9.  
    "y": 161
  10.  
    },
  11.  
    "rb": {
  12.  
    "x": 1684,
  13.  
    "y": 778
  14.  
    }
  15.  
    },
  16.  
    "ocr": [
  17.  
    {
  18.  
    "confidence": 0.8265708088874817,
  19.  
    "index": 0,
  20.  
    "label": "120",
  21.  
    "location": {
  22.  
    "lb": {
  23.  
    "x": 403.0,
  24.  
    "y": 471.0
  25.  
    },
  26.  
    "lt": {
  27.  
    "x": 396.0,
  28.  
    "y": 434.0
  29.  
    },
  30.  
    "rb": {
  31.  
    "x": 464.0,
  32.  
    "y": 459.0
  33.  
    },
  34.  
    "rt": {
  35.  
    "x": 457.0,
  36.  
    "y": 422.0
  37.  
    }
  38.  
    }
  39.  
    }
  40.  
    ]
  41.  
    }
  42.  
    ]
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgibkia
系列文章
更多 icon
同类精品
更多 icon
继续加载