Search code examples
jsonrustjson-rpcserdeyew

Yew callback for different Json structs


I am using yew with the WebsocketService and sending jsonrpcs to a backend and receive the according answers. I have a problem to distinguish between valid and error jsonrpc answers. Within the model implementation, I create the callback via:

let callback = self.link.callback(|Json(data)| {
    Msg::WsCallback(data)
});

WsCallback is a message with the actual response:

pub enum Msg {
    // ...
    WsCallback(Result<WsResponse, Error>),
}

and the response is the actual JsonRpc format:

#[derive(Deserialize)]
pub struct WsResponse {
    jsonrpc: String,
    result: String,
    id: i32,
}

Works fine for valid answers, but how do I handle the error-case of JsonRpc responses, which looks like this:

#[derive(Deserialize)]
pub struct JsonRpcError{
    code: i32,
    message: String,
}

#[derive(Deserialize)]
pub struct WsResponseErr {
    jsonrpc: String,
    error: JsonRpcError,
    id: i32,
}

Is there some sort of match I can do on Json structs? As bonus-question: Is there a possibility to parse valid response with a result type different than String?


Solution

  • You should use a wrapper with both types and add untagged attribute for serde:

    #[derive(Deserialize)]
    #[serde(untagged)]
    pub enum JsonRpcResult {
        Ok(WsResponse),
        Err(WsResponseErr),
    }
    

    Is there a possibility to parse valid response with a result type different than String?

    Yes, and I strongly recommend you to use your custom types there. You can use any type that implement Deserialize trait instead of String. You can read here how to implement Deserialize or just use derive for your structs how you already did it above.