fix(subscribe): 修复历史 note 双重 JSON 编码导致的订阅列表 500

2.0 时代旧代码对 JSON 列显式 json.dumps,导致 note 字段在库里是
字符串而非数组,响应模型按 List[int] 校验失败返回 500。

- 新增 3.0.7 数据迁移,解析并回写字符串型 note 为真正的 JSON 数组
- Subscribe 响应模型增加 note 字符串兼容解析,脏数据按空值处理
This commit is contained in:
jxxghp
2026-08-17 10:56:31 +08:00
parent eefe1ec931
commit 77b7960b7d
3 changed files with 131 additions and 1 deletions
+24 -1
View File
@@ -1,6 +1,7 @@
import json
from typing import Optional, List, Dict, Any, ClassVar
from pydantic import BaseModel, Field, ConfigDict, model_validator
from pydantic import BaseModel, Field, ConfigDict, model_validator, field_validator
from app.schemas.media import OptionalMediaIdentityMixin
from app.schemas.types import MediaSource, MediaType
@@ -154,6 +155,28 @@ class Subscribe(OptionalMediaIdentityMixin, BaseModel):
model_config = ConfigDict(from_attributes=True)
@field_validator("note", mode="before")
@classmethod
def _normalize_legacy_note(cls, value: Any) -> Any:
"""
兼容历史字符串型 note。
2.0 时代旧代码对 JSON 列显式做了 ``json.dumps``,历史数据可能是一层
或两层 JSON 编码的字符串(如 ``'[1, 2, 3]'``),不解析会触发响应
校验 500;解析失败按空值处理,避免脏数据阻塞整个订阅列表接口。
"""
if not isinstance(value, str):
return value
parsed = value
while isinstance(parsed, str):
try:
parsed = json.loads(parsed)
except (TypeError, ValueError):
return None
if isinstance(parsed, list):
return [item for item in parsed if isinstance(item, int)]
return None
@model_validator(mode="before")
@classmethod
def _normalize_empty_strings(cls, data: Any) -> Any: