如何在Rust中用分段Struct组织API返回的JSON数据?
Rust中用嵌套Struct组织API返回的JSON数据
我从API获取到JSON格式的数据后,想用带分段的嵌套Struct来组织这些数据,比如创建包含info、data的结构,大致如下:
struct mainstruct { info : { price : "whatever", category : "something", }, data : { title : "here", description : "many", }, }
我不确定是否需要创建两个impl或者enum再包含到新Struct里?目前我通过以下代码从模拟API获取数据:
use reqwest::{Client, Error}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Product { pub id: i64, pub title: String, pub description: String, pub price: i64, pub rating: f64, pub stock: i64, pub brand: String, pub category: String, pub thumbnail: String, pub images: Vec<String>, } #[tokio::main] async fn main() -> Result<(), Error> { let product: Product = Client::new() .get("https://dummyjson.com/products/1") .send() .await? .json() .await?; println!(">>>>>> Brand is : {:#?}", product.brand); Ok(()) }
现在需要把获取到的Product数据整理成如下分段结构:
info { price : Product.price, category : Product.category, }, data { title : Product.title, description : Product.description, }
解决方案:直接定义嵌套Struct即可
不需要使用enum,也无需额外复杂的impl逻辑,直接创建嵌套Struct就能满足需求,具体步骤如下:
- 定义子结构:分别创建
Info和Data两个Struct,对应你需要的分段字段 - 定义主结构:创建包含
info和data字段的主Struct(比如命名为SectionedProduct) - 实现转换逻辑:通过
Fromtrait让原Product类型可以直接转换为新的分段结构,提升代码复用性
完整代码示例:
use reqwest::{Client, Error}; use serde::{Deserialize, Serialize}; // 原Product结构保持不变 #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Product { pub id: i64, pub title: String, pub description: String, pub price: i64, pub rating: f64, pub stock: i64, pub brand: String, pub category: String, pub thumbnail: String, pub images: Vec<String>, } // 分段子结构:Info #[derive(Debug)] pub struct Info { pub price: i64, pub category: String, } // 分段子结构:Data #[derive(Debug)] pub struct Data { pub title: String, pub description: String, } // 包含分段的主结构 #[derive(Debug)] pub struct SectionedProduct { pub info: Info, pub data: Data, } // 实现从Product到SectionedProduct的类型转换 impl From<Product> for SectionedProduct { fn from(product: Product) -> Self { SectionedProduct { info: Info { price: product.price, category: product.category, }, data: Data { title: product.title, description: product.description, }, } } } #[tokio::main] async fn main() -> Result<(), Error> { let product: Product = Client::new() .get("https://dummyjson.com/products/1") .send() .await? .json() .await?; // 转换为分段结构 let sectioned_product = SectionedProduct::from(product); println!(">>>>>> Info部分: {:#?}", sectioned_product.info); println!(">>>>>> Data部分: {:#?}", sectioned_product.data); Ok(()) }
补充说明
- 如果不需要对新的分段结构做序列化/反序列化操作,无需给
Info、Data、SectionedProduct添加#[derive(Serialize, Deserialize)];若后续需要将分段结构转为JSON,再添加即可。 - 除了使用
Fromtrait,也可以直接在代码中手动构建分段结构,比如:
但let sectioned_product = SectionedProduct { info: Info { price: product.price, category: product.category, }, data: Data { title: product.title, description: product.description, }, };Fromtrait的优势在于可以在任何需要转换的地方直接调用SectionedProduct::from(product)或product.into(),让代码更简洁复用。
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

