'How to send JSON as response in tokio & warp?

I want to post the string into the server and deserialize it and send back JSON object via warp. It works fine with strings but it wont send JSON messages to WebSocket client

#[derive(Deserialize, Debug)]
pub struct Event {
    topic: String,
    user_id: Option<usize>,
    message: String,
    password: String,
}

pub async fn publish_handler(body: Event, clients: Clients) -> Result<impl Reply> {
    if body.password != "password" {
        Ok(StatusCode::from_u16(403).unwrap())
    } else {
        clients
            .read()
            .await
            .iter()
            .filter(|(_, client)| match body.user_id {
                Some(v) => client.user_id == v,
                None => true,
            })
            .filter(|(_, client)| client.topics.contains(&body.topic))
            .for_each(|(_, client)| {
                if let Some(sender) = &client.sender {
                    let json_response: Value = serde_json::from_str(&body.message.clone()).unwrap();
                    let _ = sender.send(Ok(Message::text(json_response)));
                }
            });

        Ok(StatusCode::OK)
    }
}

Error

I get below error:

the trait bound `std::string::String: std::convert::From<serde_json::Value>` is not satisfied

Dependencies

[dependencies]
tokio = { version = "1.6.0", features = ["full"] }
tokio-stream = "0.1.6"
warp = "0.3.1"
serde = {version = "1.0", features = ["derive"] }
serde_json = "1.0"
futures = { version = "0.3", default-features = false }
uuid = { version = "0.8.2", features = ["serde", "v4"] }
reqwest = { version = "0.11", features = ["json"] }


Solution 1:[1]

Your error message the trait bound `std::string::String: std::convert::From<serde_json::Value>` is not satisfied comes from these lines:

let json_response: serde_json::Value;
Message::text(json_response) 

where text() needs a parameter that implements into string:

fn text<S: Into<String>>(s: S) -> Message {}

serde_json::Value does not implement Into<String> according to the docs (even though it does implement to_string()).

probably all you need then is:

Message::text(json_response.to_string()) 
// or if body.message is a string of some type already then
Message::text(&body.message.clone())

Also, rust tends to avoid hidden, unexpected, non-explicit heap allocations by default, and Into<String> would probably require one.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1