Use json to serialize two data types

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PoolError {
    pub code: i32,
    pub message: String,
}
#[derive(Debug)]
pub enum FetchError {
    Http(reqwest::Error),
    Pool(PoolError),
}
impl From<reqwest::Error> for FetchError {
    fn from(err: reqwest::Error) -> FetchError {
        FetchError::Http(err)
    }
}
impl From<PoolError> for FetchError {
    fn from(err: PoolError) -> FetchError {
        FetchError::Pool(err)
    }
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct PoolErrorWrapper {
    error: PoolError,
}
#[derive(Deserialize)]
#[serde(untagged)]
pub enum JsonResult {
    Success(MiningInfoResponse),
    Error(PoolError),
}
impl From<JsonResult> for Result<MiningInfoResponse, FetchError> {
    fn from(res: JsonResult) -> Self {
        match res {
            JsonResult::Success(m) => Ok(m),
            JsonResult::Error(e) => {
                let err = serde_json::from_slice::<PoolErrorWrapper>(e)?;
                Err(FetchError::Pool(err.error))
            }
        }
    }
}
pub async fn get_mining_info(&self) -> Result<MiningInfoResponse, FetchError> {
        let res = self
            .inner
            .get(self.uri_for("burst"))
            .headers((*self.headers).clone())
            .query(&GetMiningInfoRequest {
                request_type: &"getMiningInfo",
            })
            .send()
            .await
            .map_err(|e| FetchError::from(e))?
            .json::<MiningInfoResponse>()
            .await
            .map_err(|e| FetchError::from(e));
        res
    }
expected enum `std::result::Result`, found `()`
expected `&[u8]`, found struct `wallet::api::PoolError`

how to serialize these two json type?
since we send http request, there are two type error

  1. http error like 404
  2. data error like "wrong data"

I need more info. Can you post the full error messages as reported by cargo build? For example, that would tell me which lines caused the errors you posted.

error[E0308]: mismatched types
  --> src/wallet/api.rs:96:70
   |
96 |                 let err = serde_json::from_slice::<PoolErrorWrapper>(e)?;
   |                                                                      ^ expected `&[u8]`, found struct `wallet::api::PoolError`

error[E0277]: `?` couldn't convert the error to `wallet::api::FetchError`
  --> src/wallet/api.rs:96:72
   |
96 |                 let err = serde_json::from_slice::<PoolErrorWrapper>(e)?;
   |                                                                        ^ the trait `std::convert::From<serde_json::error::Error>` is not implemented for `wallet::api::FetchError`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following implementations were found:
             <wallet::api::FetchError as std::convert::From<reqwest::error::Error>>
             <wallet::api::FetchError as std::convert::From<wallet::api::PoolError>>
   = note: required by `std::convert::From::from`

You need to give from_slice a slice of bytes, but PoolError is not a slice of bytes. Maybe you wanted to parse the message field?

let err = serde_json::from_slice::<PoolErrorWrapper>(e.message.as_bytes())?;

The other error is because you have no

impl From<serde_json::error::Error> for FetchError

You probably need a third case in your enum to handle invalid json errors.

i want to realize the futures. how to serialize this function? to serialize two type error.

I don't understand what you are asking?

Change these lines to this

Err(FetchError::Pool(e))

That’s at least one of the errors. And maybe the other. That second code sample is the same code I gave you in another post.

I know when learning Rust it can be hard to understand what’s going on, but one recommendation is to pay attention to the types. If you don’t know what type variable e is, you can put this in the code let () = e; and the compiler will complain that you’re assigning the variable to the wrong type but in the process it will tell you the type of e. And then at times it just turns into taking the type you have and the type you want, and trying to figure out what gets you there.

In this case e should already be type PoolError so you can pass it directly to FetchError::PoolError. There might be a new error that pops up after that but that should get you closer.

one thing i don't understand is that.
when the http data be {code:400,msg:"pool err"}, so as we know it can't be serizial as MiningInfoResponse, it will throw out an serialize error, but do we need to re serialize it , such as json<HashMap<String,String>>(e) ??? if we not parse it, the e will be err:{code:400,msg:"pool err"}, just be a bytes?? so i am really confused

#[serde(untamed)] tells serde to try the first variant MiningInfoResponse in the enum JsonResult and if it fails try the next variant PoolError . This will only work if the fields for a successful response are different from those if there an error. If you share an example of both a successful and unsuccessful response and what your definition of MiningInfoResponse is, it would make it easier to help with the issue.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.