JSON 数据处理详解:Python中的序列化与反序列化

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在Python中通过json模块提供了完整的支持。下面我将详细讲解JSON在Python中的使用方法,包括四种核心函数:json.loads()json.dumps()json.load()json.dump()

一、JSON基础概念

1. 什么是JSON?

JSON是一种基于文本的数据格式,具有以下特点:

  • 易于人阅读和编写

  • 易于机器解析和生成

  • 完全独立于编程语言

  • 支持嵌套数据结构

2. JSON与Python数据类型对应关系

JSON类型Python类型
objectdict
arraylist
stringstr
numberint/float
true/falseTrue/False
nullNone

二、JSON核心函数详解

1. json.loads() - 从JSON字符串到Python对象

功能:将JSON格式的字符串解码为Python对象

语法

json.loads(s, *, cls=None, object_hook=None, parse_float=None, 
          parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

示例

import json

json_str = '{"name": "Alice", "age": 25, "is_student": false, "courses": ["Math", "Science"]}'
python_dict = json.loads(json_str)

print(python_dict)
# 输出: {'name': 'Alice', 'age': 25, 'is_student': False, 'courses': ['Math', 'Science']}

print(type(python_dict))  # <class 'dict'>

参数说明

  • object_hook: 可选函数,用于自定义解码后的字典对象

  • parse_float: 指定浮点数解码函数

  • parse_int: 指定整数解码函数

2. json.dumps() - 从Python对象到JSON字符串

功能:将Python对象编码为JSON格式的字符串

语法

json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
          allow_nan=True, cls=None, indent=None, separators=None,
          default=None, sort_keys=False, **kw)

示例

import json

python_dict = {
    'name': 'Bob',
    'age': 30,
    'is_employed': True,
    'skills': None,
    'languages': ['Python', 'JavaScript']
}

json_str = json.dumps(python_dict, indent=4)
print(json_str)
# 输出:
# {
#     "name": "Bob",
#     "age": 30,
#     "is_employed": true,
#     "skills": null,
#     "languages": [
#         "Python",
#         "JavaScript"
#     ]
# }

常用参数

  • indent: 缩进空格数,美化输出

  • ensure_ascii: 是否转义非ASCII字符(设为False可保留中文等)

  • sort_keys: 是否按键排序

3. json.load() - 从文件读取JSON数据

功能:从文件对象中读取JSON数据并解码为Python对象

语法

json.load(fp, *, cls=None, object_hook=None, parse_float=None, 
         parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

示例

import json

# 假设有一个data.json文件,内容为:
# {"name": "Charlie", "score": 88.5, "passed": true}

with open('data.json', 'r', encoding='utf-8') as f:
    data = json.load(f)

print(data)  # {'name': 'Charlie', 'score': 88.5, 'passed': True}

注意事项

  • 文件需要以读模式打开

  • 文件必须包含有效的JSON内容

  • 会自动关闭文件(使用with语句时)

4. json.dump() - 将JSON数据写入文件

功能:将Python对象编码为JSON格式并写入文件

语法

json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True,
         allow_nan=True, cls=None, indent=None, separators=None,
         default=None, sort_keys=False, **kw)

示例

import json

data = {
    'product': 'Laptop',
    'price': 999.99,
    'in_stock': True,
    'specs': {'RAM': '16GB', 'Storage': '512GB SSD'}
}

with open('product.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, indent=2, ensure_ascii=False)

生成的文件内容

{
  "product": "Laptop",
  "price": 999.99,
  "in_stock": true,
  "specs": {
    "RAM": "16GB",
    "Storage": "512GB SSD"
  }
}

三、函数对比总结

函数输入源输出目标典型应用场景
json.loads()JSON字符串Python对象处理API返回的JSON字符串
json.dumps()Python对象JSON字符串准备发送给API的数据
json.load()文件对象Python对象读取本地存储的JSON配置文件
json.dump()Python对象文件对象将数据保存为JSON文件

四、高级用法与技巧

1. 处理自定义对象

默认情况下,JSON模块无法序列化自定义类的实例。可以通过以下方式解决:

方法1:使用default参数指定转换函数

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

def user_to_dict(user):
    return {'name': user.name, 'age': user.age}

user = User('Alice', 25)
json_str = json.dumps(user, default=user_to_dict)

方法2:为类添加__dict__方法

json_str = json.dumps(user.__dict__)

方法3:继承JSONEncoder

class UserEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, User):
            return {'name': obj.name, 'age': obj.age}
        return super().default(obj)

json_str = json.dumps(user, cls=UserEncoder)

2. 处理日期时间对象

JSON没有原生的日期时间类型,通常转换为字符串:

from datetime import datetime

def datetime_handler(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError("Type not serializable")

data = {'time': datetime.now()}
json_str = json.dumps(data, default=datetime_handler)

3. 处理特殊浮点值

JSON规范不支持NaNInfinity等特殊浮点值,可以通过参数控制:

data = {'value': float('nan')}
# json.dumps(data)  # 会报错
json.dumps(data, allow_nan=True)  # 在JavaScript中可解析,但不符合严格JSON规范

五、实际应用示例

1. 配置文件读写

import json
import os

# 写入配置
config = {
    'language': 'Python',
    'version': '3.9',
    'settings': {'theme': 'dark', 'font_size': 14}
}

config_path = 'config.json'
with open(config_path, 'w') as f:
    json.dump(config, f, indent=4)

# 读取配置
if os.path.exists(config_path):
    with open(config_path) as f:
        loaded_config = json.load(f)
    print(loaded_config)

2. API数据处理

import json
import requests

# 获取API数据
response = requests.get('https://api.example.com/data')
data = json.loads(response.text)

# 处理数据
filtered_data = [item for item in data if item['value'] > 10]

# 发送处理后的数据
headers = {'Content-Type': 'application/json'}
requests.post('https://api.example.com/processed', 
             data=json.dumps(filtered_data), 
             headers=headers)

3. 数据持久化

import json

# 保存用户数据
def save_users(users, filename):
    with open(filename, 'w') as f:
        json.dump([u.__dict__ for u in users], f)

# 加载用户数据
def load_users(filename):
    with open(filename) as f:
        return [User(**data) for data in json.load(f)]

六、常见问题与解决方案

Q1:JSONDecodeError: Expecting value: line 1 column 1 (char 0)

原因:尝试解析空字符串或无效JSON
解决:检查数据源是否包含有效JSON内容

Q2:TypeError: Object of type 'datetime' is not JSON serializable

原因:尝试序列化不支持的类型
解决:使用default参数提供自定义序列化方法

Q3:中文字符被转义为Unicode码

解决:设置ensure_ascii=False

json.dumps(data, ensure_ascii=False)

Q4:如何提高大JSON文件的处理性能?

建议

  • 使用ijson库处理流式大文件

  • 避免一次性加载超大文件到内存

  • 考虑使用更高效的数据格式如MessagePack

七、总结

JSON作为数据交换的标准格式,在Python中通过json模块提供了简单易用的接口:

  1. 序列化(Python→JSON):

    • json.dumps() 生成字符串

    • json.dump() 写入文件

  2. 反序列化(JSON→Python):

    • json.loads() 从字符串解析

    • json.load() 从文件读取

  3. 关键点

    • 注意数据类型转换规则

    • 处理自定义对象需要额外步骤

    • 使用indent参数美化输出

    • 处理非ASCII字符设置ensure_ascii=False

掌握这些JSON处理技巧,能够高效地在Python程序中进行数据序列化和持久化操作,为Web开发、数据分析和系统集成等场景提供坚实基础。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值