Serde_json::json!(response)["success"] == null

Hello

I am doing a POST-request

let http = reqwest::Client::new();
    let response = http
        .post("https://hcaptcha.com/siteverify")
        .form(&[
            ("secret", &(*config::HCAPTCHA_SECRET)),
            ("response", &form.h_captcha_response),
        ])
        .send()
        .await
        .expect("Failed to get response.")
        .text()
        .await
        .unwrap();

I successfully get a response.

Response {"success":false,"error-codes":["invalid-input-response"]}

Now I want to use serde_json to convert this response to JSON so I can get the value of success.

I am doing this:

serde_json::json!(response)

which yields:

"{\"success\":false,\"error-codes\":[\"invalid-input-response\"]}"

But now doing serde_json::json!(response)["success"] equals to null. What am I doing wrong? Making a struct to map the response is too complicated because the response can differ a lot depending on success/error/...

I think I got it

if serde_json::from_str::<serde_json::Value>(&response)
        .unwrap()
        .get("success")
        .unwrap()
        != &serde_json::json!(true)
    {
       /// error
    }

You don't need to serialize and deserialize the response object (generally if you find yourself doing that, you're holding your screwdriver wrong). You can just use its methods.

response.status().is_success()
3 Likes

I think you need to call .json instead of .text, in order to parse directly the response body.

It also works to parse to serde_json::Value as explained here: How can an arbitrary json structure be deserialized with reqwest get in Rust? - Stack Overflow

2 Likes

The API of hcaptcha also returns 200 OK when success == false.

Error handling is actually a difficult problem to solve when the REST API needs to support a wide variety of user agents. The common solution, as in the case of hCaptcha, is to forego the REST best practices and return errors encoded in the "application layer" of an HTTP 200 response. Because this allows the application to parse the response, even if the agent would normally discard the response body on some non-200 response codes. (This was mostly only necessary for JSONP, but the practice continues regardless.)

It's still problematic because REST itself gives agents the tools to handle errors without parsing JSON at all. Some services will give integrations a choice of APIs instead of just a one-size-fits-all least common denominator API. I know this doesn't apply here, but I wanted to point it out as a questionable decision made by the service provider.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.