大多数 "rusty" 包装 Rustson 响应并避免重复特征的方法?
Most "rusty" way to wrap Rustson responses and avoid duplicated traits?
我正在学习 Rust,但我不确定最优雅或 "rusty" 做某些事情的方式:
我正在从一个 API 中检索数据,在某些端点上 returns 一个 JSON 对象 ({ value: "resource A" }
),但在其他情况下,它 returns 一个 JSON 对象被另一个对象 ({ error: false, data: { value: "resource A" } }
) 包裹。
我正在使用 Restson 检索该数据。
我的问题是:处理不同响应的最优雅的方法是什么?我不知道如何使用某种可以接受两种 JSON 响应的抽象 Response
。
我的意思是,在这种情况下,我实现了 2 个特征,但它们具有相同的内容,所以,对我来说,它闻起来好像那里有问题。
这是一个简化的示例,因此可能存在拼写错误:
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
}
}
您有两个变体的响应,因此可以考虑基于枚举的解决方案:
#[derive(Debug, Serialize, Deserialize)]
struct ResourceA {
value: String,
}
#[derive(Debug, Serialize, Deserialize]
#[serde(untagged)]
pub enum Response {
ErrAndValue{error: bool, data: ResourceA},
Simple(ResourceA),
}
我使用了 untagged 注释来符合 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))
}
}
我正在学习 Rust,但我不确定最优雅或 "rusty" 做某些事情的方式:
我正在从一个 API 中检索数据,在某些端点上 returns 一个 JSON 对象 ({ value: "resource A" }
),但在其他情况下,它 returns 一个 JSON 对象被另一个对象 ({ error: false, data: { value: "resource A" } }
) 包裹。
我正在使用 Restson 检索该数据。
我的问题是:处理不同响应的最优雅的方法是什么?我不知道如何使用某种可以接受两种 JSON 响应的抽象 Response
。
我的意思是,在这种情况下,我实现了 2 个特征,但它们具有相同的内容,所以,对我来说,它闻起来好像那里有问题。
这是一个简化的示例,因此可能存在拼写错误:
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
}
}
您有两个变体的响应,因此可以考虑基于枚举的解决方案:
#[derive(Debug, Serialize, Deserialize)]
struct ResourceA {
value: String,
}
#[derive(Debug, Serialize, Deserialize]
#[serde(untagged)]
pub enum Response {
ErrAndValue{error: bool, data: ResourceA},
Simple(ResourceA),
}
我使用了 untagged 注释来符合 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))
}
}