常见坑
每一章对着一个报错或一个现象:先用最小的程序把它复现出来(输出是 M2 Max、macOS、rustc 1.99.0 上的原文),再到源码里找它从哪一行来,最后给出修法和检查办法。机制在前面几部分讲过的,这里只链过去,不再重复。
- data did not match any variant of untagged enum Shape:untagged 只留一句话,每个变体为什么失败都被丢了;读成
Value再逐个变体from_value才看得到真正的错误;变体顺序还会让输入读成功但读错。 - invalid type: string "1", expected u32:JSON 里的数字写成了字符串,serde_json 照
deserialize_u32的提示只读数字;只收字符串用DisplayFromStr,数字和字符串都收用PickFirst<(_, DisplayFromStr)>或自写调deserialize_any的deserialize_with;数字键 map 进了缓冲也报这句。 - missing field
x:只有字段类型自己调deserialize_option才会缺省成None;deserialize_with、newtype 包着的Option、Value、Vec缺了都报错,要加default。 - invalid type: string "...", expected a borrowed string:
&str字段遇到带转义的字符串借不成;from_reader配&str在编译期就被拒;改用String或Cow加borrow。 - unknown field
kind:flatten 加deny_unknown_fields能编译,效果却因 flatten 的对象而异,flatten 内部标签 enum 时连合法输入都失败;flatten 的Option出错时静默成None。 - u128 is not supported:
Content没有 128 位整数,内部标签、flatten 里的u128读不回,untagged 只剩 no match;toml 和 serde_urlencoded 读u128也报这句。 - Bincode does not support the serde::Deserializer::deserialize_any method:bincode、postcard 只能按提示读:内部标签、相邻标签、untagged、
Value能写不能读,flatten 写不出来,skip_serializing_if读错位。 - key must be a string:JSON 对象的键只能是字符串,元组、struct、
None当键报错,NaN 键报float key must be finite;整数、bool键会被写成字符串。 - recursion limit exceeded:serde_json 最多嵌套 127 层;
unbounded_depth能关掉限制,但嵌套深了递归会栈溢出。 - the trait bound
Rc<std::string::String>: serde::Serializeis not satisfied:Rc/Arc的实现在rcfeature 后面,因为序列化、反序列化都不保留共享,读回来是多份拷贝。 - from_reader 读文件很慢:serde_json 不缓冲,直接给
File时每个字节一次read系统调用,1.28 MB 用 483 ms;包一层BufReader是 4 ms,read_to_end加from_slice是 3 ms。 - 浮点数往返后不相等:默认的浮点解析不是正确舍入,
[0, 1)的数约 10% 读回来差最后一位;开float_roundtrip归零;NaN 和无穷写成null,读不回f64。 attempt to subtract with overflow,或者[],1,2]:手写Serialize声称serialize_seq(Some(0))却写进元素,to_string写出非法 JSON,to_string_pretty在 debug 下 panic、release 下无限写缩进。- the trait bound
Post: serde::Serializeis not satisfied(明明 derive 了):依赖树里同时有 serde 0.9 和 1.x,类型实现的是旧版的 trait,rustc 只说「名字相近」;serde 和 serde_derive 版本不配则在 cargo 解析阶段就失败。
按三条主线(怎么读这一卷)分:
| 出在哪里 | 坑 |
|---|---|
序列化主线:类型把数据推给 Serializer | 8 键必须是字符串、12 NaN 写成 null、13 谎报长度 |
反序列化主线:格式驱动 Visitor | 2 类型不符、3 缺字段、4 借不到、9 递归上限、11 from_reader 慢、12 浮点解析 |
缓冲主线:先读成 Content 再重放 | 1 untagged、5 flatten、6 u128、7 二进制格式 |
| 不在主线上:编译期 trait 不满足 | 10 Rc、14 两个 serde |
flowchart TB
q{碰到了什么}
q -->|编译错误| ce{"trait 不满足"}
ce -->|"Rc 或 Arc"| p10["10 rc feature"]
ce -->|"明明 derive 了"| p14["14 两个 serde"]
q -->|反序列化报错| de{哪种}
de -->|"untagged enum"| p1["1 untagged"]
de -->|"invalid type"| p2["2 或 4"]
de -->|"missing field"| p3["3 缺字段"]
de -->|"unknown field"| p5["5 flatten"]
de -->|"deserialize_any"| p7["7 二进制格式"]
de -->|"recursion limit"| p9["9 递归上限"]
q -->|序列化报错| p8["8 键必须是字符串"]
q -->|"结果不对或很慢"| r{哪种}
r -->|读文件慢| p11["11 from_reader"]
r -->|浮点不相等| p12["12 浮点往返"]
r -->|"JSON 非法或 panic"| p13["13 谎报长度"]
💬 关联讨论
发起讨论加载中...