解决发布web接口时数据无法JSON化的问题

解决HTTP接口传输中的JSON序列化问题

引言

当涉及到复杂的数据类型时,如浮点数、Numpy数组、pandas等,直接使用Python的json模块进行序列化可能会遇到问题。本文将解决这些问题,并提供一个通用的方案,确保数据能够顺利地通过HTTP接口传输。

目录

  1. JSON序列化的基本概念

    • 1.1 JSON简介
    • 1.2 Python中的JSON模块
    • 1.3 JSON序列化的常见问题
  2. Python中的数据类型与JSON序列化

    • 2.1 基本数据类型
    • 2.2 复杂数据类型
    • 2.3 Numpy数据类型
  3. 解决JSON序列化问题的通用方法

    • 3.1 自定义序列化函数
    • 3.2 处理浮点数
    • 3.3 处理Numpy数组
    • 3.4 处理字典和列表
  4. 代码实现与示例

    • 4.1 代码结构
    • 4.2 示例代码
    • 4.3 测试与验证
  5. 性能优化与注意事项

    • 5.1 性能优化
    • 5.2 注意事项
  6. 总结

1. JSON序列化的基本概念

1.1 JSON简介

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。JSON采用完全独立于语言的文本格式,但使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。

1.2 Python中的JSON模块

Python标准库中的json模块提供了对JSON格式的支持。通过json.dumps()函数,可以将Python对象序列化为JSON格式的字符串;通过json.loads()函数,可以将JSON格式的字符串反序列化为Python对象。

1.3 JSON序列化的常见问题

尽管json模块功能强大,但在处理某些Python数据类型时,可能会遇到无法序列化的问题。例如:

  • 浮点数NaN(Not a Number)和Infinity无法直接序列化为JSON。
  • Numpy数组:Numpy数组无法直接序列化为JSON。
  • 复杂数据类型:如自定义类实例,无法直接序列化为JSON。

2. Python中的数据类型与JSON序列化

2.1 基本数据类型

Python的基本数据类型(如整数、浮点数、字符串、布尔值等)可以直接序列化为JSON。例如:

import jsondata = {"name": "Alice","age": 30,"is_student": False
}json_str = json.dumps(data)
print(json_str)

输出:

{"name": "Alice", "age": 30, "is_student": false}

2.2 复杂数据类型

对于复杂数据类型,如字典、列表等,json模块也可以直接处理。例如:

data = {"name": "Alice","scores": [90, 85, 88],"details": {"city": "New York","zipcode": "10001"}
}json_str = json.dumps(data)
print(json_str)

输出:

{"name": "Alice", "scores": [90, 85, 88], "details": {"city": "New York", "zipcode": "10001"}}

2.3 Numpy数据类型

Numpy是Python中用于科学计算的重要库,提供了多维数组对象和各种数学函数。然而,Numpy的数据类型(如np.float32np.int64np.ndarray等)无法直接序列化为JSON。例如:

import numpy as np
import jsondata = {"name": "Alice","scores": np.array([90, 85, 88]),"age": np.int64(30)
}try:json_str = json.dumps(data)
except TypeError as e:print(f"Error: {e}")

输出:

Error: Object of type ndarray is not JSON serializable

3. 解决JSON序列化问题的通用方法

3.1 自定义序列化函数

为了解决上述问题,我们可以编写一个自定义的序列化函数,对无法直接序列化的数据类型进行处理。以下是一个通用的解决方案:

import math
import numpy as npdef json_serializable(value, float_precision=4):"""json化json.dumps,某些类型会遇到无法序列化的问题。处理单个值,确保其可以被序列化。"""if isinstance(value, float):if math.isnan(value):return None  # 使用 None 表示 NaNelif math.isinf(value):return None  # 使用 None 表示 Infinity 和 -Infinityelse:return round(value, float_precision)elif isinstance(value, np.float32):return round(float(value), float_precision)elif isinstance(value, np.ndarray):return value.tolist()  # 将 numpy 数组转换为 Python 列表elif isinstance(value, (np.int32, np.int64)):return int(value)  # 将 numpy 整数类型转换为 Python 整数elif isinstance(value, np.float64):return round(float(value), float_precision)  # 将 numpy 浮点数类型转换为 Python 浮点数elif isinstance(value, dict):return {k: json_serializable(v) for k, v in value.items()}  # 递归处理字典中的每个键值对elif isinstance(value, list):return [json_serializable(v) for v in value]  # 递归处理列表中的每个元素return value

3.2 处理浮点数

在处理浮点数时,我们需要特别注意NaNInfinity。这些值在JSON中没有直接的表示方式,因此我们需要将其转换为None

def handle_float(value, float_precision=4):if math.isnan(value):return None  # 使用 None 表示 NaNelif math.isinf(value):return None  # 使用 None 表示 Infinity 和 -Infinityelse:return round(value, float_precision)

3.3 处理Numpy数组

Numpy数组无法直接序列化为JSON,因此我们需要将其转换为Python列表。

def handle_numpy_array(value):return value.tolist()  # 将 numpy 数组转换为 Python 列表

3.4 处理字典和列表

对于字典和列表,我们需要递归地处理其中的每个元素。

def handle_dict(value, float_precision=4):return {k: json_serializable(v, float_precision) for k, v in value.items()}def handle_list(value, float_precision=4):return [json_serializable(v, float_precision) for v in value]

4. 代码实现与示例

4.1 代码结构

我们将上述功能整合到一个函数中,并提供一个示例来展示如何使用该函数。

import math
import numpy as npdef json_serializable(value, float_precision=4):"""json化json.dumps,某些类型会遇到无法序列化的问题。处理单个值,确保其可以被序列化。"""if isinstance(value, float):if math.isnan(value):return None  # 使用 None 表示 NaNelif math.isinf(value):return None  # 使用 None 表示 Infinity 和 -Infinityelse:return round(value, float_precision)elif isinstance(value, np.float32):return round(float(value), float_precision)elif isinstance(value, np.ndarray):return value.tolist()  # 将 numpy 数组转换为 Python 列表elif isinstance(value, (np.int32, np.int64)):return int(value)  # 将 numpy 整数类型转换为 Python 整数elif isinstance(value, np.float64):return round(float(value), float_precision)  # 将 numpy 浮点数类型转换为 Python 浮点数elif isinstance(value, dict):return {k: json_serializable(v, float_precision) for k, v in value.items()}  # 递归处理字典中的每个键值对elif isinstance(value, list):return [json_serializable(v, float_precision) for v in value]  # 递归处理列表中的每个元素return value# 示例数据
data = {"name": "Alice","scores": np.array([90, 85, 88]),"age": np.int64(30),"height": np.float32(1.68),"weight": np.float64(60.5),"is_student": False,"details": {"city": "New York","zipcode": "10001"}
}# 使用自定义序列化函数
serialized_data = json_serializable(data)# 输出序列化后的数据
import json
print(json.dumps(serialized_data, indent=4))

4.2 示例代码

以下是完整的示例代码:

import math
import numpy as np
import jsondef json_serializable(value, float_precision=4):"""json化json.dumps,某些类型会遇到无法序列化的问题。处理单个值,确保其可以被序列化。"""if isinstance(value, float):if math.isnan(value):return None  # 使用 None 表示 NaNelif math.isinf(value):return None  # 使用 None 表示 Infinity 和 -Infinityelse:return round(value, float_precision)elif isinstance(value, np.float32):return round(float(value), float_precision)elif isinstance(value, np.ndarray):return value.tolist()  # 将 numpy 数组转换为 Python 列表elif isinstance(value, (np.int32, np.int64)):return int(value)  # 将 numpy 整数类型转换为 Python 整数elif isinstance(value, np.float64):return round(float(value), float_precision)  # 将 numpy 浮点数类型转换为 Python 浮点数elif isinstance(value, dict):return {k: json_serializable(v, float_precision) for k, v in value.items()}  # 递归处理字典中的每个键值对elif isinstance(value, list):return [json_serializable(v, float_precision) for v in value]  # 递归处理列表中的每个元素return value# 示例数据
data = {"name": "Alice","scores": np.array([90, 85, 88]),"age": np.int64(30),"height": np.float32(1.68),"weight": np.float64(60.5),"is_student": False,"details": {"city": "New York","zipcode": "10001"}
}# 使用自定义序列化函数
serialized_data = json_serializable(data)# 输出序列化后的数据
print(json.dumps(serialized_data, indent=4))

4.3 测试与验证

为了验证我们的解决方案是否有效,我们可以使用不同的数据类型进行测试。例如:

# 测试数据
test_data = {"name": "Bob","scores": np.array([95, 88, 92]),"age": np.int64(25),"height": np.float32(1.75),"weight": np.float64(70.2),"is_student": True,"details": {"city": "Los Angeles","zipcode": "90001"},"special_values": {"nan": float("nan"),"inf": float("inf"),"-inf": float("-inf")}
}# 使用自定义序列化函数
serialized_test_data = json_serializable(test_data)# 输出序列化后的数据
print(json.dumps(serialized_test_data, indent=4))

输出:

{"name": "Bob","scores": [95, 88, 92],"age": 25,"height": 1.75,"weight": 70.2,"is_student": true,"details": {"city": "Los Angeles","zipcode": "90001"},"special_values": {"nan": null,"inf": null,"-inf": null}
}

5. 性能优化与注意事项

5.1 性能优化

在处理大量数据时,递归调用可能会导致性能问题。为了优化性能,可以考虑以下几点:

  • 缓存结果:对于已经处理过的数据类型,可以缓存结果以避免重复计算。
  • 并行处理:对于大规模数据,可以考虑使用并行处理技术(如多线程或多进程)来加速序列化过程。

5.2 注意事项

  • 数据丢失:在处理特殊值(如NaNInfinity)时,我们将其转换为None。这可能会导致数据丢失,因此在实际应用中需要谨慎处理。
  • 兼容性:不同的JSON库可能对特殊值的处理方式不同,因此在跨平台或跨语言的数据交换中,需要确保兼容性。

6. 总结

本文详细探讨了在HTTP接口传输中遇到的JSON序列化问题,并提供了一个通用的解决方案。通过自定义序列化函数,我们可以处理浮点数、Numpy数组等复杂数据类型,确保数据能够顺利地通过HTTP接口传输。在实际应用中,我们还需要注意性能优化和数据兼容性问题,以确保系统的稳定性和可靠性。

通过本文的学习,读者应该能够理解并掌握如何解决JSON序列化中的常见问题,并在实际项目中应用这些知识。希望本文能为读者在处理HTTP接口数据传输时提供有价值的参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/62103.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SlickGrid复选框

分析 1、先在columns首列添加复选框; 2、在SlickGrid注册刚添加的复选框; 3、添加复选框变化事件; 4、注册按钮点击事件,点击获取已选中的行。 展示 代码 复选框样式(CSS) .slick-cell-checkboxsel {bac…

摄像头原始数据读取——V4L2(userptr模式,V4L2_MEMORY_USERPTR)

摄像头原始数据读取——V4L2(userptr模式,V4L2_MEMORY_USERPTR) 用户指针方式允许用户空间的应用程序分配内存,并将内存地址传递给内核中的驱动程序。驱动程序直接将数据填充到用户空间的内存中,从而避免了数据的拷贝过程。 流程: 通过VIDI…

浏览器缓存与协商缓存

1. 强缓存(Strong Cache) 定义 强缓存是指在缓存的资源有效期内,浏览器会直接使用缓存中的数据,而不会发起网络请求。也就是说,浏览器会直接从本地缓存读取资源,不会与服务器进行任何交互。 如何控制强缓…

AI 写作(一):开启创作新纪元(1/10)

一、AI 写作:重塑创作格局 在当今数字化高速发展的时代,AI 写作正以惊人的速度重塑着创作格局。AI 写作在现代社会中占据着举足轻重的地位,发挥着不可替代的作用。 随着信息的爆炸式增长,人们对于内容的需求日益旺盛。AI 写作能够…

RabbitMQ 篇-深入了解延迟消息、MQ 可靠性(生产者可靠性、MQ 可靠性、消费者可靠性)

??博客主页:【_-CSDN博客】** 感谢大家点赞??收藏评论** 文章目录 ???1.0 RabbitMQ 的可靠性 ? ? ? ? 2.0 发送者的可靠性 ? ? ? ? 2.1 生产者重试机制 ? ? ? ? 2.2 生产者确认机制 ? ? ? ? 2.2.1 开启生产者确认机制 ? ? ? ? 2.2…

问:SpringBoot核心配置文件都有啥,怎么配?

在SpringBoot的开发过程中,核心配置文件扮演着至关重要的角色。这些文件用于配置应用程序的各种属性和环境设置,使得开发者能够灵活地定制和管理应用程序的行为。本文将探讨SpringBoot的核心配置文件,包括它们的作用、区别,并通过…

【机器学习】数据集合集!

本文将为您介绍经典、热门的数据集,希望对您在选择适合的数据集时有所帮助。 1 privacy 更新时间:2024-11-26 访问地址: GitHub 描述: 此存储库包含 TensorFlow Privacy(一种 Python)的源代码 库,其中包…

Linux V4L2框架介绍

linux V4L2框架介绍 V4L2框架介绍 V4L2,全称Video for Linux 2,是Linux操作系统下用于视频数据采集设备的驱动框。它提供了一种标准化的方式使用户空间程序能够与视频设备进行通信和交互。通过V4L2接口,用户可以方便地实现视频图像数据的采…

[网安靶场] [更新中] UPLOAD LABS —— 靶场笔记合集

GitHub - c0ny1/upload-labs: 一个想帮你总结所有类型的上传漏洞的靶场一个想帮你总结所有类型的上传漏洞的靶场. Contribute to c0ny1/upload-labs development by creating an account on GitHub.https://github.com/c0ny1/upload-labs 0x01:UPLOAD LABS 靶场初识…

SpringBoot社团管理:用户体验优化

3系统分析 3.1可行性分析 通过对本社团管理系统实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本社团管理系统采用SSM框架,JAVA作为开发语言&#…

org.apache.log4j的日志记录级别和基础使用Demo

org.apache.log4j的日志记录级别和基础使用Demo,本次案例展示,使用是的maven项目,搭建的一个简单的爬虫案例。里面采用了大家熟悉的日志记录插件,log4j。来自apache公司的开源插件。 package com.qian.test;import org.apache.log…

2024年第15届蓝桥杯C/C++组蓝桥杯JAVA实现

目录 第一题握手,这个直接从49累加到7即可,没啥难度,后面7个不握手就好了,没啥讲的,(然后第二个题填空好难,嘻嘻不会) 第三题.好数​编辑 第四题0R格式 宝石组合 数字接龙 最后一题:拔河 第…

matlab根据excel表头筛选表格数据

有如下表格需要筛选: 如果要筛选style中的A,color中的F2,num中的3。 代码如下: clear;clc; file_Pathstrcat(F:\csdn\,test1.xlsx); %表格路径、文件名 E1readtable(file_Path,Sheet,1); %读取表格中的字母和数字,1代表第一个…

day05(单片机高级)PCB基础

目录 PCB基础 什么是PCB?PCB的作用? PCB的制作过程 PCB板的层数 PCB设计软件 安装立创EDA PCB基础 什么是PCB?PCB的作用? PCB(Printed Circuit Board),中文名称为印制电路板,又称印刷…

【机器学习】——朴素贝叶斯模型

💻博主现有专栏: C51单片机(STC89C516),c语言,c,离散数学,算法设计与分析,数据结构,Python,Java基础,MySQL,linux&#xf…

【Android+多线程】异步 多线程 知识总结:基础概念 / 多种方式 / 实现方法 / 源码分析

1 基本概念 1.1 线程 定义:一个基本的CPU执行单元 & 程序执行流的最小单元 比进程更小的可独立运行的基本单位,可理解为:轻量级进程组成:线程ID 程序计数器 寄存器集合 堆栈注:线程自己不拥有系统资源&#…

Error: Invalid version flag: if 问题排查

问题描述: 国产化系统适配,arm架构的centos 在上面运行docker 启动后需要安装数据库 依赖perl 在yum install -y perl 时提示: “Error: Invalid version flag: if”

华为鸿蒙内核成为HarmonyOS NEXT流畅安全新基座

HDC2024华为重磅发布全自研操作系统内核—鸿蒙内核,鸿蒙内核替换Linux内核成为HarmonyOS NEXT稳定流畅新基座。鸿蒙内核具备更弹性、更流畅、更安全三大特征,性能超越Linux内核10.7%。 鸿蒙内核更弹性:元OS架构,性能安全双收益 万…

五种创建k8s的configMap的方式及configmap使用

configmap介绍 Kubernetes 提供了 ConfigMap 来管理应用配置数据,将配置信息从容器镜像中解耦,使应用更灵活、可移植。 1、基于一个目录来创建ConfigMap ​ 你可以使用 kubectl create configmap 基于同一目录中的多个文件创建 ConfigMap。 当你基于目…

如何将本地项目上传到gitee上

本地项目代码想上传到gitee管理、使用idea编辑器操作上传 新建仓库、填写信息 创建好了仓库,把HTTPS路径复制一下,之后会用到。 用命令进入项目进行git初始化 执行命令: cd 文件夹 git init 用idea把项目打开,然后配置一下gi…