seanmonstar/warp

warp::reply::json does not convert numbers properly

dsxmachina opened this issue · 2 comments

Hello,

I stumbled across a funny bug when using the warp::reply::json function on a datatype, that contains an u64 field.

An u64 is not properly encoded, if the number is too big.

It seems to me, that the number is treated as a float during the conversion, because it is not converted properly.

For example: My input number is 16716100060113585857, but the route returns 16716100060113586000.

A more qualified example:

Take this datatype

/// Return type of the [`list_tiles_handler`]
#[derive(Debug, Serialize, Deserialize)]
struct Tile {
    name: String,
    hash: u64,
}

And this route:

async fn return_tile_dummy() -> ApiResult<impl Reply> {
    // Create a dummy tile
    let tile = Tile {
        name: "maximum".to_string(),
        hash: u64::MAX,
    };

    // Build a json here with serde as comparison
    let tile_str = serde_json::to_string(&tile).unwrap();
    debug!("json: {tile_str}");

    Ok(warp::reply::json(&tile))
}

The route returns the following output:

{
  "name": "maximum",
  "hash": 18446744073709552000
}

However, the correct output would be:

{
  "name": "maximum",
  "hash": 18446744073709551615
}

I compared this to the output from serde_json - the serde implementation seems to work as expected here,
so it must be a warp issue.

warp uses serde_json directly, as seen here:

inner: serde_json::to_vec(val).map_err(|err| {

Could you perhaps have been using a newer serde_json, and doing a cargo update where you were using warp would fix it?

Sorry, my bad - everything in your software works fine.
I piped the output from warp through jq to view it on the cmdline:

curl 127.0.0.1:8000/test/ | jq

Not using jq gives the correct result.