Rust – Working with JSON– Part 2.

I spent quite some time trying to figure out what Rust crate to use for serializing some from an object into JSON.  I debated quite a bit between rustc_serialize and serde.  I wound up choosing serde as it seems to be the direction things are going and it’s reported to be more efficient and have more features.  I did not independently verify this.

My problem was a little more difficult than the simple example of serializing a single level of JSON.  I had multiple nested levels complicated with the fact that I wanted to allow an already serialized string to be tacked on as an element so I can treat it like a chunk of anonymous JSON passed in by a caller.

This is on nightly rust vs. stable.  We like to live on the edge!

rustc 1.9.0-nightly (998a6720b 2016-03-07)

Essentially I wanted to serialize something like this:

{item1: "1234",
item2, "2345"
item3: {
item4: "3456"
item5: {
item6: "4567",
item7: '5678"
}

There were a lot of compiler errors being caused by not having this in the right place and with the right combination of extern crate.  In my lib.rs I needed the following at the top of the file.  This would also go for main.rs if you have a main instead of a lib.

#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;

In my Cargo.toml I had the following dependencies:

[dependencies]
serde = "0.6.11"
serde_json = "0.6.0"
serde_macros = "0.6.11"

In my library module (not lib.rs, but the implementation of my library module.) I included the following:

extern crate serde_json;
use self::serde_json::Value;



#[derive(Serialize, Deserialize, Debug)]
pub struct TopLevelItem {
item1: String,
item2: String,
item3: Option,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct SecondLevelItem {
item4: String,
item5: Value, //This is needed to allow a JSON string to be added
// without the serializer escaping this as a string again.
}

Later on in my code, I create these objects…

let top = TopLevelItem {
item1: "1234".to_string(),
item2: "2345".to_string(),
item3: Some(SecondLevelItem {
item4: "3456".to_string(),
item5: data, //This is just another serialized structure which I needed to //anonymize and treat item5 as just a chunk of JSON.  I was unable to do //this with 
rustc_serialize.  This was a case that worked out nicely.
})
};

 

Then I serialize the data to a string…


let serialized = serde_json::to_string(&body).unwrap();
println!("serialized: {}", serialized);

If the serialized data needs to be converted to a static str and you can’t get
a static str from a String, thus you need to slice.  This was needed before I could use the data in the body of an HTTP POST request using hyper.
let body_slice: &str = &serialized[..];

Overall, this was obviously a lot more involved than serializing in JavaScript.  It’s not too bad after getting the macros and features setup correctly.  That took some time and experimentation.  That’s all for now.  I will continue to blog on my experiences with Rust.

 

Advertisements