Rust 最";锈迹斑斑;如何包装Russon反应并避免重复特征?

Rust 最";锈迹斑斑;如何包装Russon反应并避免重复特征?,rust,serde,Rust,Serde,我正在学习生锈,但我不确定做某些事情的最优雅或“生锈”的方式: 我从一个API中检索数据,该API在某些端点上返回一个JSON对象({value:“resource a”}),但在其他情况下,它返回一个由另一个对象包装的JSON对象({error:false,data:{value:“resource a”}) 我用它来检索数据 我的问题是:处理不同反应的最优雅方式是什么?我不知道如何使用某种抽象的Response来接受这两种JSON响应 我的意思是,在这个例子中,我实现了两个特性,但它们都有相

我正在学习生锈,但我不确定做某些事情的最优雅或“生锈”的方式:

我从一个API中检索数据,该API在某些端点上返回一个JSON对象(
{value:“resource a”}
),但在其他情况下,它返回一个由另一个对象包装的JSON对象(
{error:false,data:{value:“resource a”}

我用它来检索数据

我的问题是:处理不同反应的最优雅方式是什么?我不知道如何使用某种抽象的
Response
来接受这两种JSON响应

我的意思是,在这个例子中,我实现了两个特性,但它们都有相同的内容,所以,对我来说,闻起来好像有什么不对劲

这是一个简化的示例,因此可能存在打字错误:

use restson::{RestPath, RestClient, Error};

#[derive(Debug, Serialize, Deserialize)]
struct Response<T> {
    error: bool,
    data: T
}

#[derive(Debug, Serialize, Deserialize)]
struct ResourceA {
    value: String,
}

// HERE: How do I remove this duplication?  
impl<'a> RestPath<(&'a str, String)> for ResourceA {
    fn get_path(params: (i8, String, &str)) -> Result<String, Error> {
        let (resource, id) = params;
        Ok(format!("{}/{}", resource, id))
    }
}
impl<'a, T> RestPath<(&'a str, String)> for Response<T> {
    fn get_path(params: (&str, String)) -> Result<String, Error> {
        let (resource, id) = params;
        Ok(format!("{}/{}", resource, id))
    }
}

pub struct Client {
    client: RestClient,
}

impl Client {
    pub fn new() -> Client {
        Client {
            client: RestClient::new("http://my.client").unwrap(),
        }
    }

    pub fn get_resource_a(&mut self, id: String) -> ResourceA {
        let params = ("a", id);
        self.client.get(params).unwrap()
    }

    pub fn get_resource_a2(&mut self, id: String) -> ResourceA {
        let params = ("a2", id);
        let response: Response<ResourceA> = self.api_client.get(params).unwrap();
        response.data
    }
}
使用restson::{RestPath,RestClient,Error};
#[派生(调试、序列化、反序列化)]
结构响应{
错误:布尔,
数据:T
}
#[派生(调试、序列化、反序列化)]
结构资源{
值:字符串,
}
//这里:如何删除此重复?
资源整合{
fn get_path(参数:(i8、字符串和str))->Result{
let(资源,id)=参数;
Ok(格式!(“{}/{}”,资源,id))
}
}
请求响应{
fn获取路径(参数:(&str,字符串))->Result{
let(资源,id)=参数;
Ok(格式!(“{}/{}”,资源,id))
}
}
发布结构客户端{
客户:RestClient,
}
impl客户端{
pub fn new()->客户端{
客户{
客户端:RestClient::新建(“http://my.client“”。展开(),
}
}
pub fn get_resource_a(&mut self,id:String)->resource a{
设params=(“a”,id);
self.client.get(params.unwrap())
}
pub fn get_resource_a2(&mut self,id:String)->ResourceA{
设params=(“a2”,id);
let response:response=self.api_client.get(params.unwrap();
答复.数据
}
}

您的响应有两个变量,因此可以考虑使用基于枚举的解决方案:

#[derive(Debug, Serialize, Deserialize)]
struct ResourceA {
    value: String,
}

#[derive(Debug, Serialize, Deserialize]
#[serde(untagged)]
pub enum Response {
    ErrAndValue{error: bool, data: ResourceA},
    Simple(ResourceA),
}
我已经使用注释来符合json格式:

{ value: "resource A" }
{ error: false, data: { value: "resource A" } }
然后将您的
RestPath
impl缩减为:

impl<'a> RestPath<(&'a str, String)> for Response {
    fn get_path(params: (&str, String)) -> Result<String, Error> {
        let (resource, id) = params;
        Ok(format!("{}/{}", resource, id))
    }
}
impl用于响应{
fn获取路径(参数:(&str,字符串))->Result{
let(资源,id)=参数;
Ok(格式!(“{}/{}”,资源,id))
}
}

我曾考虑使用
枚举
,但我不知道
未标记
,这是关键部分。获得响应后,如何访问
资源A
数据?通过
匹配使用模式匹配,请参阅。无论如何,一个很好的地方,看看锈迹模式是谢谢你。后来我意识到这是得到它的方法