Python “安全”序列化复杂对象的问题

35 天前
 gosky
需求是:
接口里,有多处渲染图片的逻辑
想把渲染图片的逻辑放到一个个单独的渲染接口

原接口返回的响应,原本带了几个图片的 base64 ,现在改为带几个图片的渲染参数
前端拿到渲染参数,拼成一个图片 url ,再请求 ——当然,这里必须是 get ,渲染参数也不能嵌套
渲染接口,接到渲染参数,再渲染图片,返回一个图片响应到前端

渲染参数结构大致是这样的:
{
code: "123",
type: "xyz",
param: "..."
}

这个渲染参数,是一个两层结构
具体的渲染参数都在 param 中,code 和 type 只是用来找到具体的渲染口子
因为渲染接口只能是 get ,param 给前端必须是字符串
后端拿到渲染参数第一步,解析出 code 和 type ,找到渲染口子。渲染口子内部再解析 param
之前没多想,把渲染参数 json 序列化,赋值给 param
没想到 json 序列化渲染参数时,会将 param 的 json 进行转义…… 导致反序列化时,param 反序列化报错

当然,有几个可行的方案:
一、ensure_ascii=False 不转义。这会影响全局。因为渲染参数响应,它的序列化是全局逻辑
二、忽略渲染参数的两层结构,直接完整的序列化和反序列化
三、param 先 json 序列化,再 base64 安全编码。这个问题是多了一部操作,且输出结果人类不可读
四,反序列化 param 时,先反转义

求一个更加优雅的方案

我需要的,也许是一个“安全”的序列化方法, 能将 param 数据,序列化为不需要转义的数据。但 python 没有 safe 的 json 方法。base64 倒是一般都有
js 有一个库,https://www.npmjs.com/package/qs ,可以将 js 嵌套对象、数组对象编码为查询字符串
但 python 好像没这样的库
1025 次点击
所在节点    Python
9 条回复
tianzhongs
35 天前
可以使用自定义的编码方式来处理这个问题。思路如下:
对于 param 中的数据,将其键值对按照一定规则拼接成字符串,而不是直接使用 JSON 序列化。
例如,如果 param 是 {"key1": "value1", "key2": "value2"},可以将其拼接为 key1=value1&key2=value2 的形式。
在前端和后端约定好这个编码规则。
前端在发送请求时,按照这个规则将 param 中的数据拼接成字符串,然后将整个渲染参数对象构建成 URL 的查询参数形式。
后端接收到请求后,先解析出 code 和 type ,然后根据约定的规则将 param 部分的字符串再解析回键值对的形式。
这样做的好处有:
不需要依赖复杂的第三方库或者特殊的设置(如 ensure_ascii=False ),并且完全符合只能使用 GET 请求且参数不能嵌套的要求。
避免了 JSON 序列化可能带来的转义问题,同时也没有增加过多的复杂操作(相比于先序列化再 base64 编码的方式)。
输出的结果相对简洁且人类可读程度较高,只要了解规则,在调试等情况下也比较容易理解。
sagaxu
35 天前
JSON 编码解码,是 JSON 规范,不会因为转义不转义失败。
URL 的 Query String ,也有自己的编码规范。

两件事情是完全不相干的,要分别处理,难不成你指望 JSON 序列化后的东西直接拼 URL 里用?
tolbkni
35 天前
```python
from urllib.parse import parse_qs
y = parse_qs('a=c')
```
gosky
35 天前
@tianzhongs param 内部是嵌套的哦
gosky
35 天前
@sagaxu 前面分析不到位
准确地说,就是要把 param 安全编码,作为查询参数
sagaxu
35 天前
@gosky 常规做法是先 JSON 序列化变 str ,再 URL 转义拼参数中,后端拿到 str 后直接 JSON 解码得到原始参数
MoYi123
35 天前
问题最关键的 param 是怎么样子的, 让你用 param: "..." 这样三个点跳过了.
gosky
35 天前
@MoYi123 不固定哦 可能有嵌套结构和列表
MoYi123
35 天前
@gosky 所以需要你给一些例子啊.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1064982

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX