Rust中API JSON反序列化:处理字段为Vec或Null的异常问题
解决JSON反序列化时null与Vec类型不兼容的问题
问题背景
API返回的JSON数据如下:
[ { "id":"b8b2f91952f1fb757663073fa8f6be73", "name":"test1", "colors":[ { "name":"Red", "number":"0" }, { "name":"Blue", "number":"1" } ] }, { "id":"91ff6b1fb7b8b2f57663073952fa8e73", "name":"test2", "colors": null } ]
对应的Rust结构体定义:
#[derive(Serialize, Deserialize, Debug)] struct FinalScores { id: String, name: String, colors: Vec<Colors> } #[derive(Serialize, Deserialize, Debug)] struct Colors{ name: String, number: String }
反序列化代码:
let score_request_url = "https://api.test.com"; let score_response = reqwest::get(score_request_url).await?; let score_infos: Vec<FinalScores> = score_response.json().await?;
运行时出现错误:
invalid type: null, expected a string
错误原因
结构体中colors字段被定义为Vec<Colors>,属于非可选的数组类型,但API返回的该字段存在null值,serde默认不支持将null直接映射到非可选的非空类型,导致反序列化失败。
解决方案
方案1:将字段改为可选类型
把colors的类型改为Option<Vec<Colors>>,这样API返回null时会被反序列化为None,返回数组时则为Some(Vec<Colors>),完整结构体定义:
#[derive(Serialize, Deserialize, Debug)] struct FinalScores { id: String, name: String, colors: Option<Vec<Colors>> } #[derive(Serialize, Deserialize, Debug)] struct Colors{ name: String, number: String }
这种方案会保留原始数据中是否为null的信息,后续业务逻辑可以通过判断Some/None来分别处理。
方案2:将null自动转为空数组
如果业务上不需要区分null和空数组,可以使用serde的属性将null映射为空Vec,同时可选地在序列化时跳过空数组(避免输出冗余内容),结构体定义:
use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize, Debug)] struct FinalScores { id: String, name: String, #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] colors: Vec<Colors> } #[derive(Serialize, Deserialize, Debug)] struct Colors{ name: String, number: String }
#[serde(default)]:反序列化时,若字段为null或缺失,会使用Vec的默认值(空数组)#[serde(skip_serializing_if = "Vec::is_empty")]:序列化时,如果数组为空则不输出该字段,可根据需求去掉此属性。
内容的提问来源于stack exchange,提问作者GranBoh
相关产品推荐
相关产品推荐

