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

Learning Rust for ex C++/Java developers (Part 1)

I’ve decided to start learning Rust.  It’s starting to be used across Mozilla and Mozilla has been heavily involved in defining it.

Additionally, I’ve been focused on JS  for a couple years now and this seems a nice language to get back to my C++/Java roots.  One of the main tutorials I’m reading is  here.

Rust is a strongly typed language and it’s main selling point is memory safety.  Rust will be a good language of choice for drivers or other systems programming.  Rust also has convenient ways to connect to other languages as a stack with many languages is quite commonplace these days.

Building and Running

Tools in Rust seem quite simple at first glance.  You can quickly build by running rustc.  Rust also has a sweet build and packaging system called cargo.  I found all this quite simple to get going with the basics.  I believe the “up and running” phase to be easier than Java and C++

First Impressions

Safety First!

I like how Rust makes safety a priority.  You’ll find TONS of safety checks built into Rust. For example, when you’re indexing into a vector you need to use a usize vs. an int; otherwise, you’ll get a compiler error which could save you from future grief.

Patterns

Rust has pretty powerful pattern matching capabilities.  Here’s one really cool thing:

In C++/Java a standard switch/case example:

switch (x) {
case 1:
// do something
break;
case 2:
// do the same thing as case 1
break;
default:
// do the default
break;
}

becomes the following in Rust:

match x {
case 1:
1|2 => // do something
_ => // do the default
}

Sweet!  A lot more brief in Rust.  One of the big selling points of Rust is the safety.  IF you forget to add a catchall ‘_’ you will get a compile time error.  Rust is demanding exhaustiveness here.

Traits

Initially, traits are a little difficult to grasp.  I started thinking of them as something similar to an interface in Java.  Interfaces are specified and then implemented inside of a class in Java.  In Rust, they are specified and then implemented inside of the struct.  Rust does have a trait called “drop.”  This is similar to destructor capabilities in C++.  It allows you to run some code when a variable goes out of scope.  You could use this to clean up resources that were used.  Additionally, it could be used to implement a reference count.

Testing

I took a cursory look at how unit tests can be written and it seems like a clean design.  There is an option to include the tests in the same file as the implementation or include a separate tests module.  The infrastructure seems quite simple and is integrated right in with cargo.  I particularly liked this.

Overall, I’m very enthusiastic about Rust and there is still lots to learn!