Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

u128 doesn't work for Value #502

Closed
alexeuler opened this issue Oct 25, 2018 · 9 comments
Closed

u128 doesn't work for Value #502

alexeuler opened this issue Oct 25, 2018 · 9 comments

Comments

@alexeuler
Copy link

alexeuler commented Oct 25, 2018

Looks like there's a bug in serde_json. This program:

#[macro_use]
extern crate serde_json;
use std::str::FromStr;

fn main() {
    let string = format!("{}", u128::max_value());
    println!("{}", string);
    let val = serde_json::value::Value::from_str(&string);
    let val2 = serde_json::to_value(u128::max_value());
    println!("{:#?}, {:#?}", val, val2);
}

outputs:

340282366920938463463374607431768211455
Ok(
    Number(
        340282366920938500000000000000000000000.0
    )
), Err(
    Error("u128 is not supported", line: 0, column: 0)
)

playground

if you put arbitrary_precision feature, then Value works 100% without cutting precision, if you do it via u128 => String => Value. However direct conversion u128 => Value with to_value results in error.

@dtolnay
Copy link
Member

dtolnay commented Oct 25, 2018

Thanks! I would accept a PR to support u128 => Value in the case that arbitrary_precision is enabled.

@josecelano
Copy link

Hi, I'm getting the same error with this code:

use serde::Serialize;

extern crate serde_json;

#[derive(Serialize)]
struct Data {
    num: u128,
}

fn main() {
    println!("{}", serde_json::json!(Data { num: 1 }))
}
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/serde-json-u128-bug`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("u128 is not supported", line: 0, column: 0)', src/main.rs:11:20
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Code: https://github.com/josecelano/serde-json-u128-bug/blob/main/src/main.rs

Using serde 1.0.152 and serde_json 1.0.91:

[[package]]
name = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
 "serde_derive",
]

[[package]]
name = "serde_json"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
 "itoa",
 "ryu",
 "serde",
]

@honeycomb-cheesecake
Copy link

I too am getting the u128 is not supported error when using serde_json::from_str(...) method. Similar struct layout to @josecelano above. Is it not supported?

@dtolnay
Copy link
Member

dtolnay commented Feb 8, 2023

Fixed in serde_json v1.0.93.

@honeycomb-cheesecake
Copy link

Hi, with serde_json v1.0.93 it's now working fine for serialisation, but when I use let payload = serde_json::from_str::<MyType>(...);, I'm still getting the u128 not supported error. Am I missing something? When I change to u64 it all works, so am I missing a setting?

@dtolnay
Copy link
Member

dtolnay commented Feb 8, 2023

Here is what I tried and it seems to work.

use serde::Deserialize;
use serde_json::json;

#[derive(Deserialize, Debug)]
pub struct Data {
    pub num: u128,
}

fn main() {
    let j = r#" {"num":1} "#;
    println!("{:?}", serde_json::from_str::<Data>(j).unwrap());

    let j = json!({"num": 1});
    println!("{:?}", serde_json::from_value::<Data>(j).unwrap());
}

@honeycomb-cheesecake
Copy link

Okay, so I did some digging and came up with the following. Is there a different handling when it comes to deserializing enum?

Works fine:

#[derive(Debug, serde::Deserialize)]
#[serde(rename = "a", tag = "type")]
struct A {
  test: u128
}

...
match serde_json::from_str::<A>(&text) {
  Ok(a) => {
    info!("{:#?}", a);
    info!("{:#?}", a.test);
  }
  Err(err) => {
    error!("{}", err.to_string());
  }
};

Fails with u128 is not supported:

#[derive(Debug, serde::Deserialize)]
#[serde(tag = "type")]
enum Opts {
    #[serde(rename = "a")]
    A { test: u128 },
}

...

match serde_json::from_str::<Opts>(&text) {
    Ok(Opts::A { test }) => {
        info!("{:#?}", test);
    }
    Err(err) => {
        error!("{}", err.to_string());
    }
};

@honeycomb-cheesecake
Copy link

Have I made a mistake somewhere? Any guidance would be much appreciated.

@jonasbb
Copy link

jonasbb commented Feb 13, 2023

Have I made a mistake somewhere? Any guidance would be much appreciated.

Internal tagging is implemented with buffering because the content could come before the tag. But the Content type does not support 128-bit values, and thus you see the error. See these other issues serde-rs/serde#2230 and serde-rs/serde#1183.

@serde-rs serde-rs locked and limited conversation to collaborators Mar 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

No branches or pull requests

5 participants