use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
pub struct ConvertResponse {
#[serde(default)]
pub status: i32,
#[serde(default)]
pub item_url: Option<String>,
#[serde(default)]
pub coupon_click_url: Option<String>,
#[serde(default)]
pub shorturl: Option<String>,
#[serde(default)]
pub shorturl2: Option<String>,
#[serde(default)]
pub tkl: Option<String>,
#[serde(default)]
pub tao_id: Option<String>,
#[serde(default)]
pub goods_detail: Option<GoodsDetail>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct ConvertByTklResponse {
#[serde(default)]
pub status: i32,
#[serde(default)]
pub content: Option<String>,
#[serde(default)]
pub tao_id: Option<String>,
#[serde(default)]
pub plat: Option<String>,
#[serde(default)]
pub plat2: Option<String>,
#[serde(default)]
pub is_youquan: Option<String>,
#[serde(default)]
pub pic: Option<String>,
#[serde(default)]
pub cid1: Option<String>,
#[serde(default)]
pub cid1_name: Option<String>,
#[serde(default)]
pub cid2: Option<String>,
#[serde(default)]
pub cid2_name: Option<String>,
#[serde(default)]
pub volume: Option<String>,
#[serde(default, rename = "commentCount")]
pub comment_count: Option<String>,
#[serde(default)]
pub title: Option<String>,
#[serde(default)]
pub tao_title: Option<String>,
#[serde(default)]
pub size: Option<String>,
#[serde(default)]
pub quanhou_jiage: Option<String>,
#[serde(default)]
pub tkrate3: Option<String>,
#[serde(default)]
pub tkfee3: Option<String>,
#[serde(default)]
pub coupon_info_money: Option<String>,
#[serde(default)]
pub nick: Option<String>,
#[serde(default)]
pub result_tkl: Option<String>,
#[serde(default)]
pub result_url: Option<String>,
#[serde(default)]
pub chunwenzi: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct BatchConvertResponse {
#[serde(default)]
pub status: i32,
#[serde(default)]
pub data: Option<Vec<BatchConvertItem>>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct BatchConvertItem {
#[serde(default)]
pub relation_id: Option<String>,
#[serde(default)]
pub item_url: Option<String>,
#[serde(default)]
pub coupon_click_url: Option<String>,
#[serde(default)]
pub tkl: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct QueryOrdersResponse {
#[serde(default)]
pub status: i32,
#[serde(default)]
pub data: Option<QueryOrdersData>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct QueryOrdersData {
#[serde(default)]
pub has_next: Option<bool>,
#[serde(default)]
pub results: Option<Vec<OrderInfo>>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct OrderInfo {
#[serde(default)]
pub trade_id: Option<String>,
#[serde(default)]
pub trade_parent_id: Option<String>,
#[serde(default)]
pub num_iid: Option<String>,
#[serde(default)]
pub item_title: Option<String>,
#[serde(default)]
pub item_img: Option<String>,
#[serde(default)]
pub item_num: Option<i32>,
#[serde(default)]
pub item_price: Option<String>,
#[serde(default)]
pub alipay_total_price: Option<String>,
#[serde(default)]
pub pub_share_pre_fee: Option<String>,
#[serde(default)]
pub pub_share_fee: Option<String>,
#[serde(default)]
pub total_commission_rate: Option<String>,
#[serde(default)]
pub tk_status: Option<i32>,
#[serde(default)]
pub tk_create_time: Option<String>,
#[serde(default)]
pub tk_paid_time: Option<String>,
#[serde(default)]
pub tk_earning_time: Option<String>,
#[serde(default)]
pub relation_id: Option<String>,
#[serde(default)]
pub special_id: Option<String>,
#[serde(default)]
pub seller_shop_title: Option<String>,
#[serde(default)]
pub seller_nick: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct CreateTklResponse {
#[serde(default)]
pub status: i32,
#[serde(default)]
pub tkl: Option<String>,
#[serde(default)]
pub model: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct ParseItemIdResponse {
#[serde(default)]
pub status: i32,
#[serde(default)]
pub num_iid: Option<String>,
#[serde(default)]
pub tao_id: Option<String>,
#[serde(default)]
pub title: Option<String>,
#[serde(default)]
pub pic: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct GoodsDetail {
#[serde(default)]
pub code: Option<String>,
#[serde(default)]
pub type_one_id: Option<String>,
#[serde(default)]
pub tao_id: Option<String>,
#[serde(default)]
pub title: Option<String>,
#[serde(default)]
pub jianjie: Option<String>,
#[serde(default)]
pub pict_url: Option<String>,
#[serde(default)]
pub user_type: Option<String>,
#[serde(default)]
pub seller_id: Option<String>,
#[serde(default)]
pub shop_dsr: Option<String>,
#[serde(default)]
pub volume: Option<String>,
#[serde(default)]
pub size: Option<String>,
#[serde(default)]
pub quanhou_jiage: Option<String>,
#[serde(default)]
pub tkrate3: Option<String>,
#[serde(default)]
pub yongjin_type: Option<String>,
#[serde(default)]
pub coupon_id: Option<String>,
#[serde(default)]
pub coupon_start_time: Option<String>,
#[serde(default)]
pub coupon_end_time: Option<String>,
#[serde(default)]
pub coupon_info_money: Option<String>,
#[serde(default)]
pub coupon_total_count: Option<String>,
#[serde(default)]
pub coupon_remain_count: Option<String>,
#[serde(default)]
pub coupon_info: Option<String>,
#[serde(default)]
pub juhuasuan: Option<String>,
#[serde(default)]
pub taoqianggou: Option<String>,
#[serde(default)]
pub haitao: Option<String>,
#[serde(default)]
pub jiyoujia: Option<String>,
#[serde(default)]
pub jinpaimaijia: Option<String>,
#[serde(default)]
pub pinpai: Option<String>,
#[serde(default)]
pub pinpai_name: Option<String>,
#[serde(default)]
pub yunfeixian: Option<String>,
#[serde(default)]
pub nick: Option<String>,
#[serde(default)]
pub small_images: Option<String>,
#[serde(default)]
pub white_image: Option<String>,
#[serde(default)]
pub tao_title: Option<String>,
#[serde(default)]
pub provcity: Option<String>,
#[serde(default)]
pub shop_title: Option<String>,
#[serde(default)]
pub zhibo_url: Option<String>,
#[serde(default, rename = "sellCount")]
pub sell_count: Option<String>,
#[serde(default, rename = "commentCount")]
pub comment_count: Option<String>,
#[serde(default)]
pub favcount: Option<String>,
#[serde(default)]
pub score1: Option<String>,
#[serde(default)]
pub score2: Option<String>,
#[serde(default)]
pub score3: Option<String>,
#[serde(default, rename = "creditLevel")]
pub credit_level: Option<String>,
#[serde(default, rename = "shopIcon")]
pub shop_icon: Option<String>,
#[serde(default)]
pub taobao_url: Option<String>,
#[serde(default)]
pub category_id: Option<String>,
#[serde(default)]
pub category_name: Option<String>,
#[serde(default)]
pub level_one_category_id: Option<String>,
#[serde(default)]
pub level_one_category_name: Option<String>,
#[serde(default)]
pub tkfee3: Option<String>,
#[serde(default)]
pub coupon_click_url: Option<String>,
#[serde(default)]
pub item_url: Option<String>,
#[serde(default)]
pub shorturl: Option<String>,
#[serde(default)]
pub shorturl2: Option<String>,
#[serde(default)]
pub tkl: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct SearchGoodsResponse {
#[serde(default)]
pub status: i32,
#[serde(default)]
pub content: Option<Vec<SearchGoodsItem>>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct SearchGoodsItem {
#[serde(default)]
pub code: Option<String>,
#[serde(default)]
pub type_one_id: Option<String>,
#[serde(default)]
pub tao_id: Option<String>,
#[serde(default)]
pub title: Option<String>,
#[serde(default)]
pub jianjie: Option<String>,
#[serde(default)]
pub pict_url: Option<String>,
#[serde(default)]
pub user_type: Option<String>,
#[serde(default)]
pub seller_id: Option<String>,
#[serde(default)]
pub shop_dsr: Option<String>,
#[serde(default)]
pub volume: Option<String>,
#[serde(default)]
pub size: Option<String>,
#[serde(default)]
pub quanhou_jiage: Option<String>,
#[serde(default)]
pub date_time_yongjin: Option<String>,
#[serde(default)]
pub tkrate3: Option<String>,
#[serde(default)]
pub yongjin_type: Option<String>,
#[serde(default)]
pub coupon_id: Option<String>,
#[serde(default)]
pub coupon_start_time: Option<String>,
#[serde(default)]
pub coupon_end_time: Option<String>,
#[serde(default)]
pub coupon_info_money: Option<String>,
#[serde(default)]
pub coupon_total_count: Option<String>,
#[serde(default)]
pub coupon_remain_count: Option<String>,
#[serde(default)]
pub coupon_info: Option<String>,
#[serde(default)]
pub juhuasuan: Option<String>,
#[serde(default)]
pub taoqianggou: Option<String>,
#[serde(default)]
pub haitao: Option<String>,
#[serde(default)]
pub jiyoujia: Option<String>,
#[serde(default)]
pub jinpaimaijia: Option<String>,
#[serde(default)]
pub pinpai: Option<String>,
#[serde(default)]
pub pinpai_name: Option<String>,
#[serde(default)]
pub yunfeixian: Option<String>,
#[serde(default)]
pub nick: Option<String>,
#[serde(default)]
pub small_images: Option<String>,
#[serde(default)]
pub white_image: Option<String>,
#[serde(default)]
pub tao_title: Option<String>,
#[serde(default)]
pub provcity: Option<String>,
#[serde(default)]
pub shop_title: Option<String>,
#[serde(default)]
pub zhibo_url: Option<String>,
#[serde(default, rename = "sellCount")]
pub sell_count: Option<String>,
#[serde(default, rename = "commentCount")]
pub comment_count: Option<String>,
#[serde(default)]
pub favcount: Option<String>,
#[serde(default)]
pub score1: Option<String>,
#[serde(default)]
pub score2: Option<String>,
#[serde(default)]
pub score3: Option<String>,
#[serde(default, rename = "creditLevel")]
pub credit_level: Option<String>,
#[serde(default, rename = "shopIcon")]
pub shop_icon: Option<String>,
#[serde(default)]
pub item_url: Option<String>,
#[serde(default)]
pub category_id: Option<String>,
#[serde(default)]
pub category_name: Option<String>,
#[serde(default)]
pub level_one_category_id: Option<String>,
#[serde(default)]
pub level_one_category_name: Option<String>,
#[serde(default)]
pub tkfee3: Option<String>,
#[serde(default)]
pub biaoqian: Option<String>,
#[serde(default)]
pub tag: Option<String>,
#[serde(default)]
pub date_time: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_convert_response_deserialize() {
let json = r#"{
"status": 200,
"item_url": "https://s.click.taobao.com/xxx",
"tkl": "淘口令内容"
}"#;
let response: ConvertResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.status, 200);
assert_eq!(
response.item_url,
Some("https://s.click.taobao.com/xxx".to_string())
);
assert_eq!(response.tkl, Some("淘口令内容".to_string()));
}
#[test]
fn test_convert_by_tkl_response_deserialize() {
let json = r#"{
"status": 200,
"content": "转换后的文案",
"tao_id": "123456789",
"plat": "1",
"result_tkl": "新淘口令"
}"#;
let response: ConvertByTklResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.status, 200);
assert_eq!(response.content, Some("转换后的文案".to_string()));
assert_eq!(response.tao_id, Some("123456789".to_string()));
assert_eq!(response.plat, Some("1".to_string()));
assert_eq!(response.result_tkl, Some("新淘口令".to_string()));
}
#[test]
fn test_query_orders_response_deserialize() {
let json = r#"{
"status": 200,
"data": {
"has_next": true,
"results": [
{
"trade_id": "123456",
"item_title": "测试商品",
"tk_status": 3
}
]
}
}"#;
let response: QueryOrdersResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.status, 200);
assert!(response.data.is_some());
let data = response.data.unwrap();
assert_eq!(data.has_next, Some(true));
assert!(data.results.is_some());
let results = data.results.unwrap();
assert_eq!(results.len(), 1);
assert_eq!(results[0].trade_id, Some("123456".to_string()));
}
#[test]
fn test_create_tkl_response_deserialize() {
let json = r#"{
"status": 200,
"tkl": "新生成的淘口令"
}"#;
let response: CreateTklResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.status, 200);
assert_eq!(response.tkl, Some("新生成的淘口令".to_string()));
}
#[test]
fn test_parse_item_id_response_deserialize() {
let json = r#"{
"status": 200,
"num_iid": "987654321",
"title": "商品标题"
}"#;
let response: ParseItemIdResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.status, 200);
assert_eq!(response.num_iid, Some("987654321".to_string()));
assert_eq!(response.title, Some("商品标题".to_string()));
}
#[test]
fn test_goods_detail_deserialize() {
let json = r#"{
"tao_id": "123456789",
"title": "商品标题",
"quanhou_jiage": "99.00",
"tkrate3": "20.00",
"tkl": "淘口令"
}"#;
let detail: GoodsDetail = serde_json::from_str(json).unwrap();
assert_eq!(detail.tao_id, Some("123456789".to_string()));
assert_eq!(detail.title, Some("商品标题".to_string()));
assert_eq!(detail.quanhou_jiage, Some("99.00".to_string()));
assert_eq!(detail.tkrate3, Some("20.00".to_string()));
assert_eq!(detail.tkl, Some("淘口令".to_string()));
}
#[test]
fn test_response_with_missing_fields() {
let json = r#"{"status": 200}"#;
let response: ConvertResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.status, 200);
assert!(response.item_url.is_none());
assert!(response.tkl.is_none());
}
}