Another Serde issue - 2nd set of eyes?

HTTP response:

Ok("{\"order\":{\"id\":13175178,\"status\":\"ok\",\"partner_id\":\"3a8bbee1-5184-4ffe-8a0c-294fbad1aee9\"}}")

My structs:

    #[derive(Deserialize)]
    struct OrderResponse {
        order: OrderData,
    }

    #[derive(Deserialize)]
    struct OrderData {
        id: i64,
        status: String,
    }

Error:

Could not parse response body: error decoding response body

I'm doing stuff like this all over our codebase and for the life of me can't figure out what is wrong here. The JSON parses fine in a parser.

(partner_id is ignored and that is fine - serde doesn't mind. I did try adding it to OrderData with the same result.)

Same as last time, that looks like some reqwest error and not a serde error.

Maybe try this to make headway as per the prior discussion.

-.map_err::<String, _>(|e| format!("Could not parse response body: {}", e))
+.map_err::<String, _>(|e| format!("Could not parse response body: {:?}", e))
2 Likes

First, I deserved that chastisement.

Secondly, I think this is the best programming forum I've ever participated in. You guys rock!

Yes, I need to hard-wire the difference between Display and Debug. So, :? got me this:

Could not parse response body: reqwest::Error { kind: Decode, source: Error("EOF while parsing a value", line: 1, column: 0) }

which is even more perplexing to me (have not encountered this before).

I'll dig into it, but, if you have more knowledge to share, by all means.

Nothing negative intended :slight_smile:.

"line 1 column 0" probably translates to "empty response", for whatever that's worth.

1 Like

Another thing you can do is download the body with bytes, print that out, and then turn it into your struct after.

let body = r.bytes().unwrap();
eprintln!("Body: {}", String::from_utf8_lossy(&body));
let t: T = serde_json::from_slice(&body).unwrap();

This is the response:

Ok("{\"order\":{\"id\":13175237,\"status\":\"ok\",\"partner_id\":\"3a8bbee1-5184-4ffe-8a0c-294fbad1aee9\"}}")

(It's completely reproducible, FWIW, and this comes from a very widely-used public API.)

This is clearly not the response, because it would deserialize fine. Rust Playground

Unless you mean it's the response verbatim, in which case of course you'll get the error, that's not valid JSON. Rust Playground But that's not the error you're getting.

1 Like

I meant the response wrapped in a Some, of course.

The response posted is one that results from an identical request, done immediately before so I can log the response. I checked that removing it results in the same error, so it's not effecting anything.

Oh, it's not the same as last time: This endpoint really is POST.

I'm going to guess it's somehow trying to parse the body before it's downloaded?

It should be fine if you're using the json feature of reqwest though...

1 Like

The exact same code is used for many other requests.

Ok, I have some bug in my (heavily abstracted) HTTP library. I created a new, bare, reqwest POST from scratch and it works.

Yes, the error indicates the response is somehow being consumed already. What is quite odd, though, is that the same library code works for other POSTS (and GETs).

I will post it when I find it.

Well, it took about five seconds of just looking at the code. I added the "innocuous" check for valid UTF-8 recently:

        .and_then(|mut response| {
            let mut buf = String::new();
            response
                .read_to_string(&mut buf)
                .expect("HTTP response not valid UTF-8");
            if buf.contains("error") {
                Err(format!("Received Error Response: {}", buf))
            } else {
                response
                    .json::<T>()
                    .map_err::<String, _>(|e| format!("Could not parse response body: {:?}", e))
            }
        })

Ugh. I wasted a couple hours on this. (And you guys wasted time too.)

I fixed it like this... obviously I already had the response in text!

        .and_then(|mut response| {
            let mut buf = String::new();
            response
                .read_to_string(&mut buf)
                .expect("HTTP response not valid UTF-8");
            if buf.contains("error") {
                Err(format!("Received Error Response: {}", buf))
            } else {
                serde_json::from_str(&buf)
                    .map_err(|e| format!("Could not parse response body: {:?}", e))
            }
1 Like

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.