serde-rs / json Goto Github PK
View Code? Open in Web Editor NEWStrongly typed JSON library for Rust
License: Apache License 2.0
Strongly typed JSON library for Rust
License: Apache License 2.0
It currently looks like this:
fn serialize_u64(&mut self, value: u64) -> Result<()> {
write!(&mut self.writer, "{}", value).map_err(From::from)
}
I tested the following variation and it made an astonishing 20% difference in the bench_log benchmarks (294 MB/s vs 244 MB/s).
if value == 0 {
self.writer.write_all(b"0").map_err(From::from)
} else {
let mut scratch = [0u8; 20];
let mut len = 0;
while value > 0 {
scratch[19 - len] = (value % 10) as u8 + b'0';
value /= 10;
len += 1;
}
self.writer.write_all(&scratch[20-len..20]).map_err(From::from)
}
That is enough to motivate looking for a better solution, or contributing a fix to Rust for whatever is making write!
slow.
This unit test caught my eye and does not make sense to me.
("{\"Cat\":[]}", Error::Syntax(ErrorCode::EOFWhileParsingValue, 1, 9)),
The Animal::Cat
variant looks like Cat { age: usize, name: String }
. Not clear where the EOF is coming from but it is not right.
In the spaceapi-rs crate, we're implementing the Space API. The crate basically provides the structs for all types in the spec, as well as the serialization and deserialization code.
Right now we're using rustc-serialize. The problem is how rustc-serialize handles optional values. In the Space API spec, there are some values that must be either absent, or contain a value. So "phone": "012 345 67 89"
is fine, not specifying a phone is also fine, but "phone": null
is invalid according to the spec. (You could consider the value a non-nullable type.)
rustc-serialize always serializes an Option::None
to null
. So we created our own enum called Optional
that can be either Value(T)
or Absent
. The unfortunate result of that is that we have to write custom serialization code for each and every one of our types: https://github.com/coredump-ch/spaceapi-rs/blob/master/src/status.rs#L175-L188
Skimming through the documentation, I didn't see a way to do this more easily with serde. Did I miss something? Or if not, would it be possible to implement something like that in serde?
Let me know if there is a better venue to discuss possible changes to serde.
Currently, the easiest way to do serialization is to do e.g.:
let obj: MyType=serde_json::from_slice(&my_buf);
I think it would look “cleaner” if you could write it as an associated function on a type, e.g.:
let obj=MyType::from_json_slice(&my_buf);
// cf. MyType::new()
There's currently the Deserialize
trait which does this but constructing a Deserializer is very verbose. One way to implement this would be:
trait JsonDeserialize: serde::Deserialize {
fn from_json_slice(v: &[u8]) -> Result<Self,JsonError> {
serde_json::from_slice(v)
}
// etc. for _str, _iter, _reader
}
impl<T: serde::Deserialize> JsonDeserialize for T {}
Thoughts?
I'm looking to generate de/serialization for json tagged union messages from an external rest api, eg.
{ type: "error", message: "wrong"}
or { type:"ok", response: { a: 1, b: 2}}
.
It looks like this can't be done with macros, but is this the correct way to do it?
Obviously it would be much easier if the json matched this:
#[derive(Serialize, Deserialize, Debug)]
enum Message {
Ok{ resp: Response }
Error{ message: String}
}
This occurs only when I include the preserve_order
feature.
serde_json = { version = "0.7", features = ["preserve_order"] }
Serializing control characters such as "\x01"
results in these characters being passed through, ie "\"\x01\""
rather than the correct "\"\\u0001\""
. The JSON spec is quite clear that these characters must be escaped, and at least one JSON implementation (Swift's) rejects the unescaped variant as invalid JSON.
I'm happy to provide a patch, not sure if you prefer that or to write your own.
The following program should result in an error when deserializing the string “{}” because the bar
field is missing. However, the call to visitor.missing_field
returns an Ok
result.
Expected output:
CHECK
Actual output:
CHECK
thread '<main>' panicked at 'called `Result::unwrap_err()` on an `Ok` value: Foo { bar: [] }', ../src/libcore/result.rs:787
Process didn't exit successfully: `target/debug/serde-test` (exit code: 101)
Program source code:
extern crate serde;
extern crate serde_json;
#[derive(Debug)]
pub struct Foo {
pub bar: Vec<String>,
}
impl serde::Deserialize for Foo {
fn deserialize<D>(d: &mut D) -> Result<Self, D::Error>
where D: serde::Deserializer
{
enum Field {
Bar,
}
impl serde::Deserialize for Field {
fn deserialize<D>(d: &mut D) -> Result<Field, D::Error>
where D: serde::Deserializer
{
struct Visitor;
impl serde::de::Visitor for Visitor {
type Value = Field;
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
where E: serde::de::Error
{
match value {
"bar" => Ok(Field::Bar),
_ => Err(E::unknown_field(value)),
}
}
}
d.visit(Visitor)
}
}
struct Visitor;
impl serde::de::Visitor for Visitor {
type Value = Foo;
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: serde::de::MapVisitor
{
let mut bar = None;
loop {
match try!(visitor.visit_key()) {
Some(Field::Bar) => {
bar = Some(try!(visitor.visit_value()));
}
None => {
break;
}
}
}
try!(visitor.end());
let bar = match bar {
Some(x) => x,
None => {
println!("CHECK");
try!(visitor.missing_field("bar"))
}
};
Ok(Foo { bar: bar })
}
}
static FIELDS: &'static [&'static str] = &["bar"];
d.visit_struct("Foo", FIELDS, Visitor)
}
}
fn main() {
serde_json::from_str::<Foo>("{}").unwrap_err();
}
JSON values provide a convenience to look up nested values called Value.lookup
. The path is given separated by dots. It is impossible to escape dots in key names with the current method. I propose to use JSON pointers as described in RFC6901 as they provide a standard way to access nested values.
If you want to use JSON pointers I can also implement the change.
Currently there is a String allocated in order to be compatible with stable Rust, which does not support encoding a char
into a stack buffer. See ser.rs#L539.
This should return the iterator, and the potentially buffered but unused character. I'm not sure if it'll ever actually have a value, but returning a value that's almost always None
couldn't hurt.
When deserializing a structure from a JSON string that's missing a field, serde_json
propagates an ExpectedSomeValue
error code variant, not the MissingField
error code variant.
The program below shows the behavior.
Expected output (roughly speaking):
Got: "missing field x" at line 3 column 5
OK, got 'missing field' x
Actual output:
Got: "expected value" at line 3 column 5
BAD, got 'expected some value'
Here's the program:
extern crate serde;
extern crate serde_json;
#[derive(Debug)]
struct Foo {
x: i32,
y: i32,
}
impl serde::Deserialize for Foo {
fn deserialize<D>(d: &mut D) -> Result<Self, D::Error> where D: serde::Deserializer {
enum Field {
X,
Y,
}
impl serde::Deserialize for Field {
fn deserialize<D>(d: &mut D) -> Result<Self, D::Error> where D: serde::Deserializer {
struct Visitor;
impl serde::de::Visitor for Visitor {
type Value = Field;
fn visit_str<E>(&mut self, value: &str) -> Result<Self::Value, E>
where E: serde::de::Error
{
match value {
"x" => Ok(Field::X),
"y" => Ok(Field::Y),
_ => Err(E::unknown_field(value)),
}
}
}
d.visit(Visitor)
}
}
struct Visitor;
impl serde::de::Visitor for Visitor {
type Value = Foo;
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Foo, V::Error>
where V: serde::de::MapVisitor
{
let mut x = None;
let mut y = None;
loop {
match try!(visitor.visit_key()) {
Some(Field::X) => {
x = Some(try!(visitor.visit_value()));
}
Some(Field::Y) => {
y = Some(try!(visitor.visit_value()));
}
None => { break; }
}
}
try!(visitor.end());
let x = match x {
Some(x) => x,
None => try!(visitor.missing_field("x")),
};
let y = match y {
Some(x) => x,
None => try!(visitor.missing_field("y")),
};
let v = Foo {
x: x,
y: y,
};
Ok(v)
}
}
static FIELDS: &'static [&'static str] = &["x", "y"];
d.visit_struct("Foo", FIELDS, Visitor)
}
}
fn main() {
let s = r#"{
"y": 17
}"#;
let got = serde_json::from_str::<Foo>(&s).unwrap_err();
println!("Got: {}", got);
match got {
serde_json::Error::SyntaxError(code, _line, _column) => {
match code {
serde_json::ErrorCode::MissingField(field) => {
println!("OK, got 'missing field' {}", field);
}
serde_json::ErrorCode::ExpectedSomeValue => {
println!("BAD, got 'expected some value'");
}
_ => { println!("BAD, got some other error code variant"); }
}
}
_ => { println!("BAD, Got unexpected error variant"); }
}
}
Similar to chyh1990/yaml-rust#16 - using linked-hash-map instead of BTreeMap in serde_json::Value. This would allow preserving the order of keys in the JSON form when deserializing to a Value, and controlling the order of keys in the JSON form when serializing from a Value.
Right now serde_json rejects serializing maps with integer keys because semantically speaking, JSON only supports maps with string keys. There are workarounds in serde 0.7 with the new #[serde(serialize_with="...", deserialize_with="...)]
(see this gist), but it still can be annoying if this keeps causing problems.
Is there any real value about erroring out on non-key values?
The stream deserializer currently does not return none on the first EOF from the input stream, instead it takes two. This is related to the way the deserializer does it's peeking.
Why can't deserializer use the std Peekable
.
extern crate serde_json;
use serde_json::*;
use std::io::{self, Read};
fn main() {
let stdin = io::stdin();
let stream_deserializer: StreamDeserializer<Value, _> = StreamDeserializer::new(stdin.bytes());
for v in stream_deserializer {
match v {
Ok(value) => {
println!("{:?}", value);
},
Err(_) => println!("Encountered a json parsing error, closing"),
}
}
}
Running this you'll notice that it takes two control-D's to close the program.
It's probably just me, but I've always been confused when trying to recall the names of the as_*
functions on Value
.
I first try to use .as_str
, because that name is popular in std
for methods returning a &str
. Then I fail, and next I try .as_string
and it succeeds. The problem is, after that I try to call .as_integer
because that was the logic I used in the previous stage ("use the fully qualified name"). Then I fail again, so instead I try .as_number
because that's the terminology used in the JSON spec. And I fail once more. At this point I give up and open the browser to read the documentation, realizing the method was .as_i64
.
It seems that those names were inherited from rustc-serialize
. I can see the rationale used to decide the current names, which corresponds to the names of the enum variants (I64
, U64
, F64
, String
, Boolean
). But personally, I think using .as_<resulting_type>
as the names has several advantages:
.as_str
returns &str
, .as_i64
returns i64
, and .as_bool
returns bool
, and so on..as_i32
or .as_i16
, it would be straightforward. Even as_str
(the one returning &str
) and as_string
(the one returning String
) could coexist!The only (but possibly big) disadvantage is, of course, it is a breaking change. (And I missed the 0.7 timeframe due to my laziness!) But this could be alleviated by introducing a deprecation period.
What's your thoughts on this?
The current behavior of StreamDeserializer is that if it hits an error, that same error is returned in perpetuity which is typically not what you want. (If that is what you want, it is easy to implement that behavior atop what I propose below.)
Suppose we have a stream deserializer that expects to read a stream of Strings. If it receives the input "a" {"b": 0} "c"
, a reasonable thing to expect as output would be "a" (error) "c"
because the second JSON object failed to deserialize to a String.
On the other hand, if the input is not a valid JSON stream I believe the StreamDeserializer should retain its current behavior because there is no way for it to regain its bearings in an invalid JSON stream. For example if the input is "a" {"b{{"c" "d"
, I would expect the output to be "a" (error) (error) (error...)
.
Just an innocent question, I'm curious to here the reason for three types (F64
, U64
, and I64
) of what is ultimately typed in JSON as a number. This may betray the fact that I was never a low level programmer, but even if there is a low level reason I'd like to know it. Thanks for the great open source project 😊
In a simple use of the stream deserializer we have, a number larger than 18446744073709551615
will not result in an error.
Here is the output of our program.
Running `target/debug/xstream`
18446744073709551615
18446744073709551615
18446744073709551616
1
18446744073709552000
1
This should return:
Running `target/debug/xstream`
18446744073709551615
18446744073709551615
18446744073709551616
error parsing JSON
1
1
I made a small doc fix PR and received a GitCop email. I have a few issues with it:
This isn't a great experience for a new contributor!
This should be an error not a panic.
fn main() {
let data = &[b'"', b'\xed', b'\xa0', b'\x80', b'"'];
serde_json::from_slice::<String>(data).ok();
}
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Utf8Error { valid_up_to: 0 }'
Caused by this unwrap.
It should be possible to add a pointer_mut(&str) method to Value. This would allow to add and modify values. (Maybe even a delete method) I failed to add such a method because of borrow checker.
Hello! I have an API that is returning JSON with certain fields missing:
{ "one":45, "two":5, "four":17 }
{ "one":81, "three":35 }
My rust file looks something like:
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct JsonStruct {
pub one: Option<usize>,
pub two: Option<usize>,
pub three: Option<usize>,
pub four: Option<usize> }
I'm not sure if Option is the way to model missing fields, but any missing field all the fields afterwards are parsed as None. For example, when I try to parse the first example, the data returned has the fourth field parsed as None. For the second data example, I would expect the second and fourth field to be None, but the third field is also None. Great library, thanks!
I am not convinced by the justification in #48 (comment). Instead of three I64
, U64
, F64
variants I would much rather use one Number
variant backed by an arbitrary-precision number. We can keep as_i64
, as_u64
, as_f64
for convenience.
I was playing around with custom Serialize
implementation, and granted this is not a sane thing, but I would expect this to not produce the JSON string {1,2}
as it currently does.
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate serde_json;
#[derive(Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
impl serde::Serialize for Point {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer
{
serializer.visit_struct("Point", PointMapVisitor {
value: self,
state: 0,
})
}
}
struct PointMapVisitor<'a> {
value: &'a Point,
state: u8,
}
impl<'a> serde::ser::MapVisitor for PointMapVisitor<'a> {
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: serde::Serializer
{
match self.state {
0 => {
self.state += 1;
Ok(Some(try!(serializer.visit_seq_elt(&self.value.x))))
}
1 => {
self.state += 1;
Ok(Some(try!(serializer.visit_seq_elt(&self.value.y))))
}
_ => {
Ok(None)
}
}
}
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let serialized = "{\"x\": 6, \"y\": 12}";
let deserialized: Point = serde_json::from_reader(serialized.as_bytes()).unwrap();
println!("{:?}", deserialized);
}
rustc 1.8.0-nightly (303892ee1 2016-01-30)
Error:
serde_json-0.7.0/src/lib.rs:120:1: 120:19 error: use of unstable library feature 'core': the libcore library has not yet been scrutinized for stabilization in terms of structure and naming (see issue #27701)
serde_json-0.7.0/src/lib.rs:120 extern crate core;
rustc --version: rustc 1.5.0
cargo --version: cargo 0.8.0-nightly (b3273e5 2016-01-11)
Please fix this
falsetrue
should not be parsed successfully. {"a":0}{"a":1}
should be okay (although I can be convinced otherwise).
I believe that the error messages for enums and structs can be made much more useful.
Unknown field "foo" while parsing a
FooBar, expected one of "a", "b", "c" (required), "d", "e", "f" (optional).
or
Unknown variant "foo" while parsing a
FooBar, expected one of "a", "b", "c".
These error messages would make it much easier to fix typos and/or locate documentation.
meet a dependency problem, thx.
Hi !
I've been looking on the internets how to implement my own serialize/deserialize on a type (particularly on the crate time, for TimeSpec or Tm), so I can seamlessly parse a date to a json string (using strftime) ... but I couldn't find a simplified example on how to implement that on a type and how.
¿Is there any place to look for such information?
Thanks for reading and for making serde ! ♥
serde_json::from_str::<Vec<f64>>("[123456789012345678901]").unwrap();
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value:
Syntax("EOF while parsing a list", 1, 23)'
Here is the buggy code: json/src/de.rs#L294-L302. The first one needs to be a peek.
Should RFC6902 JSON Patch be implemented or is this something for a separate crate? (Patch is based on Pointer)
See serde-rs/serde#404.
From what I understand, the community has started to use the feature
unstable*
instead ofnightly*
for things that may depend on the nightly compiler. If this is the case, when we do 0.8, we should consider renaming this feature.
From JSON standard:
Insignificant whitespace is allowed before or after any token. The whitespace characters are: character tabulation (U+0009), line feed (U+000A), carriage return (U+000D), and space (U+0020). Whitespace is not allowed within any token, except that space is allowed in strings.
Recently I've moved my projects to Serde and I found it amazing, but it has several inconveniences:
FromStr
trait is not implemented for Value
, so I can't use str.parse()
ToJson
trait which improves ergonomics a lot.Value
.I've made several pull requests:
I believe that this will improve ergonomics. This will also improve compatibility with rustc-serialize
and simplify migration.
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
use std::collections::BTreeMap;
extern crate serde_json;
#[derive(Serialize, Deserialize)]
struct Bar(BTreeMap<String, i32>);
fn main() {
let mut b = Bar(BTreeMap::new());
b.0.insert(String::from("foo"), 123);
// prints {"foo":123}
println!("{}", serde_json::to_string(&b).unwrap());
let mut outer = BTreeMap::new();
outer.insert(String::from("outer"), serde_json::to_value(&b));
// prints {"outer":[{"foo":123}]}
println!("{}", serde_json::to_string(&outer).unwrap());
}
I would expect the second print to be {"outer":{"foo":123}}
.
If a ()
struct field is missing when deserializing JSON input, no error is reported. This means there's no distinction between ()
and Option<()>
.
This is related to issue #29, which is about missing Vec<_>
fields going unreported, and issue #22, which is about serde_json
reporting missing fields incorrectly in general.
The following program demonstrates the behavior for the ()
case.
Expected output: (none)
Actual output:
thread '<main>' panicked at 'Got unexpected OK result: Ok(Foo { a: () })', main.rs:91
Process didn't exit successfully: `/home/craig/art/serde_json-cmbrandenburg/issue_x_test/target/debug/issue_x_test` (exit code: 101)
extern crate serde;
extern crate serde_json;
#[derive(Debug)]
struct Foo {
a: (),
}
impl serde::Deserialize for Foo {
fn deserialize<D>(d: &mut D) -> Result<Self, D::Error>
where D: serde::Deserializer
{
enum Field {
A,
}
impl serde::Deserialize for Field {
fn deserialize<D>(d: &mut D) -> Result<Self, D::Error>
where D: serde::Deserializer
{
struct Visitor;
impl serde::de::Visitor for Visitor {
type Value = Field;
fn visit_str<E>(&mut self, value: &str) -> Result<Self::Value, E>
where E: serde::de::Error
{
match value {
"a" => Ok(Field::A),
_ => Err(E::unknown_field(value)),
}
}
}
d.visit(Visitor)
}
}
struct Visitor;
impl serde::de::Visitor for Visitor {
type Value = Foo;
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Foo, V::Error>
where V: serde::de::MapVisitor
{
let mut a = None;
loop {
match try!(visitor.visit_key()) {
Some(Field::A) => {
a = Some(try!(visitor.visit_value()));
}
None => {
break;
}
}
}
try!(visitor.end());
let a = match a {
Some(x) => x,
None => try!(visitor.missing_field("a")),
};
let v = Foo { a: a };
Ok(v)
}
}
static FIELDS: &'static [&'static str] = &["a"];
d.visit_struct("Foo", FIELDS, Visitor)
}
}
fn main() {
let s = "{}";
let got = serde_json::from_str::<Foo>(&s);
match got {
Err(serde_json::Error::SyntaxError(serde_json::ErrorCode::MissingField(field),
line,
column)) => {
assert_eq!(("a", 1, 2), (field, line, column));
}
Ok(_) => {
panic!("Got unexpected OK result: {:?}", got);
}
_ => {
panic!("Got unexpected error result: {:?}", got);
}
}
}
I have encountered what I believe to be a bug. I am using 0.7's ability to specify a custom serialize_with function. I have a struct with a string and an enum wrapping either a u64 or a vector of the same. When serializing a struct with the vector, I get a comma after the field name and colon, but before the array. If I rearrange my struct, so that the enum wrapping the vector comes first, before the other field, it behaves as expected.
See the following gist
problem code
Running this program:
extern crate serde_json;
fn main() {
serde_json::from_str::<serde_json::Value>("-0").unwrap();
}
causes:
thread '<main>' panicked at 'arithmetic operation overflowed', [...]/.cargo/registry/src/github.com-88ac128001ac3a9a/serde_json-0.6.0/src/de.rs:289
whereas I expected it to run to completion successfully with no output.
Correct me if I'm wrong, but ObjectBuilder::unwrap
doesn't actually panic!()
, right? If so, I think it should be renamed to to_value
or something like that.
I don't see a reason that this was part of the public API in the first place. GitHub search does not show any callers. The implementation has never been remotely correct (it is somewhat better as of #58 but still can produce invalid JSON).
This would be a breaking change.
Serde reports the ErrorCode::InvalidType
variant when deserializing from a Value
and a field is missing. It should report the ErrorCode::MissingField
variant—same as when deserializing from a JSON-formatted string.
The program below shows the problem.
extern crate serde;
extern crate serde_json;
#[derive(Debug)]
struct Foo {
field_1: i32,
}
impl serde::Deserialize for Foo {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: serde::Deserializer
{
enum Field {
Field1,
}
impl serde::Deserialize for Field {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: serde::Deserializer
{
struct Visitor;
impl serde::de::Visitor for Visitor {
type Value = Field;
fn visit_str<E>(&mut self, value: &str) -> Result<Self::Value, E>
where E: serde::de::Error
{
match value {
"field_1" => Ok(Field::Field1),
_ => Err(E::unknown_field(value)),
}
}
}
deserializer.deserialize(Visitor)
}
}
struct Visitor;
impl serde::de::Visitor for Visitor {
type Value = Foo;
fn visit_map<Vis>(&mut self, mut visitor: Vis) -> Result<Self::Value, Vis::Error>
where Vis: serde::de::MapVisitor
{
let mut field_1 = None;
loop {
match try!(visitor.visit_key()) {
Some(Field::Field1) => {
field_1 = Some(try!(visitor.visit_value()));
}
None => {
break;
}
}
}
try!(visitor.end());
let field_1 = match field_1 {
Some(field_1) => field_1,
None => try!(visitor.missing_field("field_1")),
};
Ok(Foo { field_1: field_1 })
}
}
static FIELDS: &'static [&'static str] = &["field_1"];
deserializer.deserialize_struct("Foo", FIELDS, Visitor)
}
}
fn main() {
let json_value = serde_json::builder::ObjectBuilder::new().unwrap();
let json_encoded = serde_json::to_string(&json_value).unwrap();
match serde_json::from_str::<Foo>(&json_encoded) {
Err(serde_json::Error::Syntax(serde_json::ErrorCode::MissingField("field_1"), 1, 2)) => (),
x @ _ => {
panic!("Got unexpected result (from_str): {:?}", x);
}
}
match serde_json::from_value::<Foo>(json_value) {
Err(serde_json::Error::Syntax(serde_json::ErrorCode::MissingField("field_1"), _, _)) => (),
x @ _ => {
panic!("Got unexpected result (from_value): {:?}", x);
}
}
}
Expected output: (success)
Actual output:
thread '<main>' panicked at 'Got unexpected result (from_value): Err(Syntax(invalid type: Unit, 0, 0))', src/main.rs:91
Process didn't exit successfully: `target/debug/serde_json_test` (exit code: 101)
Would have caught #99.
Because there wasn't a 0.6 release after 5661c78, crates depending on 0.6 are now broken because they try to upgrade to serde 0.7.
Can you release serde_json 0.6.1 please? :)
http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf specifies in the second paragraph of the introduction that JSON is agnostic about numbers, and simply represents them as a series of digits.
However, serde-json parses anything with a decimal point as a Rust f64
, which causes numbers to be read incorrectly. There is no way to avoid this because this behaviour is chosen as soon as a decimal point is encountered. This makes it impossible to use serde-json to interoperate with financial software using JSON.
I am just in the starting phase of learning Rust and am looking to add logic after I can successfully compile this example JSON from the builder. It seems that the examples only cover the simplest use cases and leaves you in the dark about assembling complex JSON documents using all of JSON features.
Example Code:
extern crate serde_json;
use serde_json::builder::ObjectBuilder;
use serde_json::Value;
fn main() {
let json = ObjectBuilder::new()
.insert("key", "12345678901234567890")
.insert_object("message", |builder| {
builder
.insert("html", "<p>Example HTML content</p>")
.insert_array("to", |builder| {
builder
.push_object(|builder| {
builder
.insert("email", "[email protected]")
})
})
.insert("important", false)
.insert("track_clicks", Value::NULL)
.insert_array("tags", |builder| {
builder
.push("password-resets")
})
.insert_array("recipient_metadata", |builder| {
builder
.push_object(|builder| {
builder
.insert("rcpt", "[email protected]")
.insert_object("values", |builder| {
builder
.insert("user_id", 123456_f64)
})
})
})
})
.insert("async", false)
.insert("ip_pool", "Main Pool")
.unwrap();
}
forge@ubuntu:~/code/contact-us-rust$ rustc -V
rustc 1.9.0 (e4e8b6668 2016-05-18)
forge@ubuntu:~/code/contact-us-rust$ clear; cargo build && cargo run
�[3;J
Compiling contact-us v0.1.0 (file:///home/forge/code/contact-us-rust)
src/main.rs:20:41: 20:52 error: no associated item named `NULL` found for type `serde_json::Value` in the current scope
src/main.rs:20 .insert("track_clicks", Value::NULL)
^~~~~~~~~~~
src/main.rs:22:21: 23:49 error: the type of this value must be known in this context
src/main.rs:22 builder
src/main.rs:23 .push("password-resets")
src/main.rs:26:21: 34:27 error: the type of this value must be known in this context
src/main.rs:26 builder
src/main.rs:27 .push_object(|builder| {
src/main.rs:28 builder
src/main.rs:29 .insert("rcpt", "[email protected]")
src/main.rs:30 .insert_object("values", |builder| {
src/main.rs:31 builder
...
src/main.rs:28:29: 29:79 error: the type of this value must be known in this context
src/main.rs:28 builder
src/main.rs:29 .insert("rcpt", "[email protected]")
src/main.rs:31:37: 32:71 error: the type of this value must be known in this context
src/main.rs:31 builder
src/main.rs:32 .insert("user_id", 123456_f64)
error: aborting due to 5 previous errors
error: Could not compile `contact-us`.
To learn more, run the command again with --verbose.
It's not clear:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.