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

背景

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

print("result", result)
dumps = json.dumps(result)
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如下:

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

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

原因

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

解决过程

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

print("result", result)
dumps = json.dumps(str(result))
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数据很简单,如果出现精度很高的数据不知道会不会出现精度损失的问题,这个问题只是想让大家不要忽略这个问题,具体的操作还是得看业务,比如笔者这里的业务数据精度要求没有这么高,即使有精度损失也是可以忽略的。

import numpy as np

p1 = 0.1
print(type(p1))

p2 = np.float32(p1)
print(type(p2))

p3 = float(p2)
print(type(p3))

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

import numpy as np

# 对numpy的数据类型进行转换
# 场景:numpy.float32类型不能写入JSON,需要转成Python的float类型
def convertNumpyDataType(data):
    if type(data) is list:
        return convertList(data)
    elif type(data) is dict:
        return convertDict(data)
    elif type(data) is np.float32:
        return convertFloat32(data)
    return data

def convertList(data):
    if type(data) is not list:
        return data

    temp = []
    for obj in data:
        temp.append(convertNumpyDataType(obj))

    return temp

def convertDict(data):
    temp = data.copy()
    if type(data) is not dict:
        return temp

    for key in data.keys():
        obj = data.get(key)
        temp.__setitem__(key, convertNumpyDataType(obj))

    return temp

def convertFloat32(data):
    return float(data)

使用场景

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

result = detectionAndOcr(img)
print("result:",result)
result = NumpyDataTypeConvert.convertNumpyDataType(result)
print("result:",result)
dumps = json.dumps(result)
print("dumps:",dumps)

这3个打印的内容如下:

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}}}]}]
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}}}]}]
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}}}]}]

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

[
    {
        "confidence": 0.9631122946739197,
        "index": 0,
        "label": "plane",
        "location": {
            "lt": {
                "x": 139,
                "y": 161
            },
            "rb": {
                "x": 1684,
                "y": 778
            }
        },
        "ocr": [
            {
                "confidence": 0.8265708088874817,
                "index": 0,
                "label": "120",
                "location": {
                    "lb": {
                        "x": 403.0,
                        "y": 471.0
                    },
                    "lt": {
                        "x": 396.0,
                        "y": 434.0
                    },
                    "rb": {
                        "x": 464.0,
                        "y": 459.0
                    },
                    "rt": {
                        "x": 457.0,
                        "y": 422.0
                    }
                }
            }
        ]
    }
]
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个错误是因为在尝试将一个float32类型的对象转换成JSON格式时出现了问题。JSON格式只能处理一些基本的数据类型,如字符串、数字、布尔值等,而不能处理一些特殊的数据类型,如float32。要解决这个问题,可以将float32类型的对象转换成JSON格式支持的数据类型,如float或int。 ### 回答2: 问题简述: 当python运行遇到这个错误时,它会提示 “typeerror: object of type float32 is not json serializable”。这个错误出现在pythonJson模块中,这通常意味着你尝试将一个不支持序列化的数据类型转换为json格式。 问题解答: 1. 为什么会出现这个类型错误? 在Python中,JSON是一种常用的数据交换格式。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它是基于JavaScript的一种数据格式,严格意义上是一种纯文本的格式,因此它通常只支持一些基本数据类型,例如字符串、数字、列表、字典等。 当你想将一个复杂数据结构转换为json格式的时候,如果你传递进去的数据类型不支持序列化,则会出现这个TypeError类型错误。 2. 怎么避免这个类型错误? 为了避免这个类型错误,遵照以下三种方法: a. 数据预处理: 在将复杂数据类型作为json格式传递之前,将该数据类型转换为支持序列化的类型。例如,如果你要传递一个包含numpy float32类型的数组,则在将其传输到json之前,你可以将其转换为python内置的float类型。 b. 自定义Encoder: 如果要转换的数值类型不支持json序列化,则可以编写一个自定义的json encoder,自定义向json编码程序注册一个新类型。例如,你可以为numpy float32、日期时间等类型编写一个自定义编码器。 c. 使用pickle代替json: 如果你的代码不要求结果以json格式编码,你可以使用Python标准库中的pickle库,它可以支持序列化几乎所有类型的Python对象,包括用户自定义的类和函数。 3. 总结 TypeError类型错误“object of type xxx is not JSON serializable”通常意味着您尝试将一个不支持json序列化的数据类型转换为json格式。因此,如果想避免这个错误,我们需要进行数据处理、自定义encoder或者使用pickle来代替json。 ### 回答3: 这个错误是因为在使用json.dumps()方法将对象序列化为json字符串时,遇到了一个不支持的数据类型——float32json格式中只支持整数、浮点数、字符串、布尔值、列表和字典等基本数据类型,而float32属于numpy库中的数据类型,不在基本数据类型范围之内。因此,在序列化过程中,系统无法将float32类型的数据转换为json字符串,从而报出了此错误。 解决这个问题有多种方法,最常见的方法是将float32类型的数据转换为支持的数据类型,例如将其转换为float类型。可以使用numpy库中的astype()方法将float32类型的数据转换为float类型,然后再进行json序列化操作。示例代码如下: import numpy as np import json # 创建一个float32类型的数组 arr = np.array([1.0, 2.0, 3.0], dtype=np.float32) # 将float32类型转换为float类型 arr = arr.astype(np.float) # 将转换后的数组序列化为json字符串 json_str = json.dumps(arr.tolist()) print(json_str) 另外,也可以使用自定义的json encoder类来处理这种特殊的数据类型,例如下面的示例代码: import json import numpy as np class NumpyEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, np.ndarray): return obj.tolist() elif isinstance(obj, np.float32): return float(obj) return json.JSONEncoder.default(self, obj) # 创建一个float32类型的数组 arr = np.array([1.0, 2.0, 3.0], dtype=np.float32) # 将数组序列化为json字符串 json_str = json.dumps(arr, cls=NumpyEncoder) print(json_str) 以上两种方法都可以解决float32类型无法序列化为json字符串的问题。需要注意的是,在处理float32类型数据时,要注意转换后的数据类型是否符合json格式的要求,以免出现其他的错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值