Deserialize large integers as InputValue::float (fixes #178)

This commit is contained in:
Paul Colomiets 2018-05-08 10:13:49 +03:00 committed by Christian Legnitto
parent 34391855af
commit 69db4c247b
2 changed files with 43 additions and 2 deletions

View file

@ -6,3 +6,13 @@
**Note:** while this is not a Rust breaking change, if you relied on the serialization format (perhaps by storing serialized data in a database or making asumptions in your client code written in another language) it could be a breaking change for your application. **Note:** while this is not a Rust breaking change, if you relied on the serialization format (perhaps by storing serialized data in a database or making asumptions in your client code written in another language) it could be a breaking change for your application.
[#151](https://github.com/graphql-rust/juniper/pull/151) [#151](https://github.com/graphql-rust/juniper/pull/151)
* Large integers (> signed 32bit) are now deserialized as floats. Previously,
they produced the "integer out of range" error. For languages that do not
have distinction between integer and floating point types (including
javascript), this means large floating point values which do not have
fractional part could not be decoded (because they are represented without
a decimal part `.0`).
[#179](https://github.com/graphql-rust/juniper/pull/179)

View file

@ -79,7 +79,12 @@ impl<'de> de::Deserialize<'de> for InputValue {
if value >= i64::from(i32::min_value()) && value <= i64::from(i32::max_value()) { if value >= i64::from(i32::min_value()) && value <= i64::from(i32::max_value()) {
Ok(InputValue::int(value as i32)) Ok(InputValue::int(value as i32))
} else { } else {
Err(E::custom("integer out of range")) // Browser's JSON.stringify serialize all numbers having no
// fractional part as integers (no decimal point), so we
// must parse large integers as floating point otherwise
// we would error on transferring large floating point
// numbers.
Ok(InputValue::float(value as f64))
} }
} }
@ -90,7 +95,12 @@ impl<'de> de::Deserialize<'de> for InputValue {
if value <= i32::max_value() as u64 { if value <= i32::max_value() as u64 {
self.visit_i64(value as i64) self.visit_i64(value as i64)
} else { } else {
Err(E::custom("integer out of range")) // Browser's JSON.stringify serialize all numbers having no
// fractional part as integers (no decimal point), so we
// must parse large integers as floating point otherwise
// we would error on transferring large floating point
// numbers.
Ok(InputValue::float(value as f64))
} }
} }
@ -247,3 +257,24 @@ impl ser::Serialize for Value {
} }
} }
} }
#[cfg(test)]
mod tests {
use serde_json::from_str;
use ast::InputValue;
#[test]
fn int() {
assert_eq!(from_str::<InputValue>("1235").unwrap(),
InputValue::int(1235));
}
#[test]
fn float() {
assert_eq!(from_str::<InputValue>("2.0").unwrap(),
InputValue::float(2.0));
// large value without a decimal part is also float
assert_eq!(from_str::<InputValue>("123567890123").unwrap(),
InputValue::float(123567890123.0));
}
}