序列化
This commit is contained in:
113
Html/apps/_docs/json_serializer_usage.md
Normal file
113
Html/apps/_docs/json_serializer_usage.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# JSON Serializer 用法文档
|
||||
|
||||
## 概述
|
||||
|
||||
`json_serializer` 是一个通用的JSON序列化工具,用于处理Python中常见的非JSON序列化类型,如`datetime`、`date`、`time`、`ObjectId`等。
|
||||
|
||||
## 支持的类型
|
||||
|
||||
- `datetime`: 转换为ISO格式字符串
|
||||
- `date`: 转换为ISO格式字符串
|
||||
- `time`: 转换为ISO格式字符串
|
||||
- `ObjectId`: 转换为字符串
|
||||
- `bytes`: 转换为UTF-8字符串
|
||||
- `set`/`frozenset`: 转换为列表
|
||||
- 其他不可序列化类型: 转换为字符串表示
|
||||
|
||||
## 安装位置
|
||||
|
||||
位于 `apps/utils/json_serializer.py`
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 导入
|
||||
|
||||
```python
|
||||
from apps.utils.json_serializer import json_serialize, json_serialize_dict, JSONEncoder
|
||||
```
|
||||
|
||||
### 函数说明
|
||||
|
||||
1. **json_serialize(obj)**: 将对象序列化为JSON字符串
|
||||
- 参数: `obj` - 要序列化的对象
|
||||
- 返回: JSON字符串
|
||||
|
||||
2. **json_serialize_dict(obj)**: 将对象转换为可JSON序列化的字典
|
||||
- 参数: `obj` - 要序列化的对象
|
||||
- 返回: 可JSON序列化的字典
|
||||
|
||||
3. **JSONEncoder**: 自定义JSON编码器类,可直接用于`json.dumps()`
|
||||
|
||||
### 示例
|
||||
|
||||
#### 基本使用
|
||||
|
||||
```python
|
||||
from datetime import datetime
|
||||
from apps.utils.json_serializer import json_serialize_dict
|
||||
|
||||
# 创建包含datetime的字典
|
||||
data = {
|
||||
"user_id": "test_user",
|
||||
"updated_at": datetime.now(),
|
||||
"scores": [85, 90, 95]
|
||||
}
|
||||
|
||||
# 序列化
|
||||
serialized = json_serialize_dict(data)
|
||||
print(serialized)
|
||||
# 输出: {"user_id": "test_user", "updated_at": "2025-12-10T15:30:45.123456", "scores": [85, 90, 95]}
|
||||
```
|
||||
|
||||
#### 在API请求中使用
|
||||
|
||||
```python
|
||||
import requests
|
||||
from apps.utils.json_serializer import json_serialize_dict
|
||||
|
||||
# 准备请求数据
|
||||
data = {
|
||||
"user_id": "test_user",
|
||||
"updated_at": datetime.now(),
|
||||
"progress": {"chapter1": "completed", "chapter2": "in_progress"}
|
||||
}
|
||||
|
||||
# 序列化数据
|
||||
serialized_data = json_serialize_dict(data)
|
||||
|
||||
# 发送请求
|
||||
response = requests.post(
|
||||
"https://api.example.com/upload",
|
||||
json=serialized_data,
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
```
|
||||
|
||||
#### 直接使用JSONEncoder
|
||||
|
||||
```python
|
||||
import json
|
||||
from datetime import datetime
|
||||
from apps.utils.json_serializer import JSONEncoder
|
||||
|
||||
# 创建数据
|
||||
data = {"updated_at": datetime.now()}
|
||||
|
||||
# 使用自定义编码器
|
||||
json_str = json.dumps(data, cls=JSONEncoder, ensure_ascii=False)
|
||||
print(json_str)
|
||||
# 输出: {"updated_at": "2025-12-10T15:30:45.123456"}
|
||||
```
|
||||
|
||||
## 应用场景
|
||||
|
||||
1. API请求中的数据序列化
|
||||
2. 保存数据到文件或数据库
|
||||
3. 跨服务数据传输
|
||||
4. 日志记录中的复杂对象序列化
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 对于自定义对象,会尝试序列化其`__dict__`属性
|
||||
- 对于无法序列化的类型,会转换为字符串表示
|
||||
- 确保导入路径正确,特别是在不同模块中使用时
|
||||
@@ -188,11 +188,17 @@ def upload_learning_progress_to_cloud(progress: Dict) -> Dict:
|
||||
base_url = config.get("ASE_ENGINE_URL", "")
|
||||
api_url = f"{base_url}/api/sync/upload"
|
||||
|
||||
# 导入JSON序列化工具
|
||||
from ...utils.json_serializer import json_serialize_dict
|
||||
|
||||
# 序列化进度数据,处理datetime等特殊类型
|
||||
serialized_progress = json_serialize_dict(progress)
|
||||
|
||||
# 构建请求参数
|
||||
payload = {
|
||||
"namespace_url": url_token, # 使用配置中的token作为namespace_url
|
||||
"user_id": progress.get("user_id", ""),
|
||||
"data": progress
|
||||
"data": serialized_progress
|
||||
}
|
||||
|
||||
# 发送POST请求
|
||||
|
||||
58
Html/apps/utils/json_serializer.py
Normal file
58
Html/apps/utils/json_serializer.py
Normal file
@@ -0,0 +1,58 @@
|
||||
import json
|
||||
from datetime import datetime, date, time
|
||||
from bson import ObjectId
|
||||
from typing import Any, Dict, List, Union
|
||||
|
||||
|
||||
class JSONEncoder(json.JSONEncoder):
|
||||
"""
|
||||
通用JSON编码器,处理常见的非JSON序列化类型
|
||||
|
||||
支持的特殊类型:
|
||||
- datetime: 转换为ISO格式字符串
|
||||
- date: 转换为ISO格式字符串
|
||||
- time: 转换为ISO格式字符串
|
||||
- ObjectId: 转换为字符串
|
||||
- 其他不可序列化类型: 转换为字符串表示
|
||||
"""
|
||||
|
||||
def default(self, obj: Any) -> Any:
|
||||
if isinstance(obj, (datetime, date, time)):
|
||||
return obj.isoformat()
|
||||
elif isinstance(obj, ObjectId):
|
||||
return str(obj)
|
||||
elif isinstance(obj, bytes):
|
||||
return obj.decode('utf-8', errors='replace')
|
||||
elif isinstance(obj, (set, frozenset)):
|
||||
return list(obj)
|
||||
elif hasattr(obj, '__dict__'):
|
||||
return obj.__dict__
|
||||
else:
|
||||
return str(obj)
|
||||
|
||||
|
||||
def json_serialize(obj: Any) -> str:
|
||||
"""
|
||||
通用JSON序列化函数,处理常见的非JSON序列化类型
|
||||
|
||||
参数:
|
||||
- obj: 要序列化的对象
|
||||
|
||||
返回:
|
||||
- str: JSON字符串
|
||||
"""
|
||||
return json.dumps(obj, cls=JSONEncoder, ensure_ascii=False)
|
||||
|
||||
|
||||
def json_serialize_dict(obj: Any) -> Dict:
|
||||
"""
|
||||
通用JSON序列化函数,将对象转换为可JSON序列化的字典
|
||||
|
||||
参数:
|
||||
- obj: 要序列化的对象
|
||||
|
||||
返回:
|
||||
- Dict: 可JSON序列化的字典
|
||||
"""
|
||||
json_str = json_serialize(obj)
|
||||
return json.loads(json_str)
|
||||
54
Html/test_datetime_serialization.py
Normal file
54
Html/test_datetime_serialization.py
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
# Add the project root to the Python path
|
||||
sys.path.insert(0, '/Users/cakecai/Documents/gitea/hsa/Html')
|
||||
|
||||
# Test the JSON serializer
|
||||
try:
|
||||
from apps.utils.json_serializer import json_serialize, json_serialize_dict, JSONEncoder
|
||||
import json
|
||||
|
||||
# Create a test dictionary with datetime object
|
||||
test_data = {
|
||||
"user_id": "test_user",
|
||||
"material_id": "test_course",
|
||||
"chapter_name": "test_chapter",
|
||||
"lesson_name": "test_lesson",
|
||||
"chat_historys": [],
|
||||
"scores": [],
|
||||
"chapter_chain_now": None,
|
||||
"updated_at": datetime.now()
|
||||
}
|
||||
|
||||
print("Testing datetime serialization...")
|
||||
print(f"Original data: {test_data}")
|
||||
print(f"Type of updated_at: {type(test_data['updated_at'])}")
|
||||
|
||||
# Test json_serialize function
|
||||
json_str = json_serialize(test_data)
|
||||
print(f"\nSerialized JSON string: {json_str}")
|
||||
|
||||
# Test json_serialize_dict function
|
||||
serialized_dict = json_serialize_dict(test_data)
|
||||
print(f"\nSerialized dictionary: {serialized_dict}")
|
||||
print(f"Type of updated_at in serialized dict: {type(serialized_dict['updated_at'])}")
|
||||
|
||||
# Test direct json.dumps with custom encoder
|
||||
json_str2 = json.dumps(test_data, cls=JSONEncoder, ensure_ascii=False)
|
||||
print(f"\nDirect json.dumps with custom encoder: {json_str2}")
|
||||
|
||||
# Verify it can be parsed back
|
||||
parsed = json.loads(json_str)
|
||||
print(f"\nParsed back from JSON: {parsed}")
|
||||
|
||||
print("\n✅ All tests passed! datetime objects can be correctly serialized to JSON.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Test failed with error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user