From 1a8a901f8696c35b86631ba01637bcafaf2614b1 Mon Sep 17 00:00:00 2001 From: musitdev Date: Sun, 12 Jan 2014 18:32:57 +0100 Subject: [PATCH 1/3] Squashed commit of the following: commit d00623d60afd460755b749ad5f94935f756f29d2 Author: musitdev Date: Sat Jan 4 22:31:40 2014 +0100 correct last comments. commit ef09d6b6d1eebbd7c713c9dad96ed7bfc19dd884 Author: musitdev Date: Thu Jan 2 20:28:53 2014 +0100 update with the last remarks. commit 46a028fe1fcdc2a7dcdd78a63001793eff614349 Author: musitdev Date: Thu Jan 2 10:17:18 2014 +0100 wrap example code in main function. commit 2472901929bef09786b7aef8ca7c89fbe67d8e3e Author: musitdev Date: Mon Dec 30 19:32:46 2013 +0100 Correct code to compile. commit ed96b2223176781743e984af0e19abcb82150f1f Author: musitdev Date: Thu Dec 5 11:32:28 2013 +0100 Correct the comment based on the PR comment. Change init call to new to reflect last change. commit 38b0390c3533a16f822a6df5f90b907bd8ed6edc Author: musitdev Date: Wed Dec 4 22:34:25 2013 +0100 correct from_utf8_owned call. commit 08bed4c5f4fadf93ec457b605a1a1354323d2f5c Author: musitdev Date: Wed Dec 4 22:12:41 2013 +0100 correct code ''' commit 02fddcbe2ab37fe842872691105bc4c5cff5abb5 Author: musitdev Date: Wed Dec 4 13:25:54 2013 +0100 correct typing error commit b26830b8ddb49f551699e791832ed20640a0fafc Author: musitdev Date: Wed Dec 4 13:18:39 2013 +0100 pass make check commit e87c4f53286122efd0d2364ea45600d4fa4d5744 Author: musitdev Date: Wed Dec 4 10:47:24 2013 +0100 Add Json example and documentation. --- src/libextra/json.rs | 223 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 1 deletion(-) diff --git a/src/libextra/json.rs b/src/libextra/json.rs index 67a15ac02fda2..88068f2cf7752 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -14,7 +14,211 @@ #[forbid(non_camel_case_types)]; #[allow(missing_doc)]; -//! json parsing and serialization +/*! +JSON parsing and serialization + +# What is JSON? + +JSON (JavaScript Object Notation) is a way to write data in Javascript. +Like XML it allows one to encode structured data in a text format that can be read by humans easily. +Its native compatibility with JavaScript and its simple syntax make it used widely. + +Json data are encoded in a form of "key":"value". +Data types that can be encoded are JavaScript types : +boolean (`true` or `false`), number (`f64`), string, array, object, null. +An object is a series of string keys mapping to values, in `"key": value` format. +Arrays are enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }). +A simple JSON document encoding a person, his/her age, address and phone numbers could look like: + +``` +{ + "FirstName": "John", + "LastName": "Doe", + "Age": 43, + "Address": { + "Street": "Downing Street 10", + "City": "London", + "Country": "Great Britain" + }, + "PhoneNumbers": [ + "+44 1234567", + "+44 2345678" + ] +} +``` + +# Rust Type-based Encoding and Decoding + +Rust provides a mechanism for low boilerplate encoding & decoding +of values to and from JSON via the serialization API. +To be able to encode a piece of data, it must implement the `extra::serialize::Encodable` trait. +To be able to decode a piece of data, it must implement the `extra::serialize::Decodable` trait. +The Rust compiler provides an annotation to automatically generate +the code for these traits: `#[deriving(Decodable, Encodable)]` + +To encode using Encodable : + +```rust +use extra::json; +use std::io; +use extra::serialize::Encodable; + + #[deriving(Encodable)] + pub struct TestStruct { + data_str: ~str, + } + +fn main() { + let to_encode_object = TestStruct{data_str:~"example of string to encode"}; + let mut m = io::mem::MemWriter::new(); + { + let mut encoder = json::Encoder::new(&mut m as &mut std::io::Writer); + to_encode_object.encode(&mut encoder); + } +} +``` + +Two wrapper functions are provided to encode a Encodable object +into a string (~str) or buffer (~[u8]): `str_encode(&m)` and `buffer_encode(&m)`. + +```rust +use extra::json; +let to_encode_object = ~"example of string to encode"; +let encoded_str: ~str = json::Encoder::str_encode(&to_encode_object); +``` + +JSON API provide an enum `json::Json` and a trait `ToJson` to encode object. +The trait `ToJson` encode object into a container `json::Json` and the API provide writer +to encode them into a stream or a string ... + +When using `ToJson` the `Encodable` trait implementation is not mandatory. + +A basic `ToJson` example using a TreeMap of attribute name / attribute value: + + +```rust +use extra::json; +use extra::json::ToJson; +use extra::treemap::TreeMap; + +pub struct MyStruct { + attr1: u8, + attr2: ~str, +} + +impl ToJson for MyStruct { + fn to_json( &self ) -> json::Json { + let mut d = ~TreeMap::new(); + d.insert(~"attr1", self.attr1.to_json()); + d.insert(~"attr2", self.attr2.to_json()); + json::Object(d) + } +} + +fn main() { + let test2: MyStruct = MyStruct {attr1: 1, attr2:~"test"}; + let tjson: json::Json = test2.to_json(); + let json_str: ~str = tjson.to_str(); +} +``` + +To decode a json string using `Decodable` trait : + +```rust +use extra::serialize::Decodable; + +#[deriving(Decodable)] +pub struct MyStruct { + attr1: u8, + attr2: ~str, +} + +fn main() { + let json_str_to_decode: ~str = + ~"{\"attr1\":1,\"attr2\":\"toto\"}"; + let json_object = extra::json::from_str(json_str_to_decode); + let mut decoder = extra::json::Decoder::new(json_object.unwrap()); + let decoded_object: MyStruct = Decodable::decode(&mut decoder); // create the final object +} +``` + +# Examples of use + +## Using Autoserialization + +Create a struct called TestStruct1 and serialize and deserialize it to and from JSON +using the serialization API, using the derived serialization code. + +```rust +use extra::json; +use extra::serialize::{Encodable, Decodable}; + + #[deriving(Decodable, Encodable)] //generate Decodable, Encodable impl. + pub struct TestStruct1 { + data_int: u8, + data_str: ~str, + data_vector: ~[u8], + } + +// To serialize use the `json::str_encode` to encode an object in a string. +// It calls the generated `Encodable` impl. +fn main() { + let to_encode_object = TestStruct1 + {data_int: 1, data_str:~"toto", data_vector:~[2,3,4,5]}; + let encoded_str: ~str = json::Encoder::str_encode(&to_encode_object); + + // To unserialize use the `extra::json::from_str` and `extra::json::Decoder` + + let json_object = extra::json::from_str(encoded_str); + let mut decoder = json::Decoder::new(json_object.unwrap()); + let decoded1: TestStruct1 = Decodable::decode(&mut decoder); // create the final object +} +``` + +## Using `ToJson` + +This example use the ToJson impl to unserialize the json string. +Example of `ToJson` trait implementation for TestStruct1. + +```rust +use extra::json; +use extra::json::ToJson; +use extra::serialize::{Encodable, Decodable}; +use extra::treemap::TreeMap; + +#[deriving(Decodable, Encodable)] // generate Decodable, Encodable impl. +pub struct TestStruct1 { + data_int: u8, + data_str: ~str, + data_vector: ~[u8], +} + +impl ToJson for TestStruct1 { + fn to_json( &self ) -> json::Json { + let mut d = ~TreeMap::new(); + d.insert(~"data_int", self.data_int.to_json()); + d.insert(~"data_str", self.data_str.to_json()); + d.insert(~"data_vector", self.data_vector.to_json()); + json::Object(d) + } +} + +fn main() { + // Seralization using our impl of to_json + + let test2: TestStruct1 = TestStruct1 {data_int: 1, data_str:~"toto", data_vector:~[2,3,4,5]}; + let tjson: json::Json = test2.to_json(); + let json_str: ~str = tjson.to_str(); + + // Unserialize like before. + + let mut decoder = json::Decoder::new(json::from_str(json_str).unwrap()); + // create the final object + let decoded2: TestStruct1 = Decodable::decode(&mut decoder); +} +``` + +*/ use std::char; use std::cast::transmute; @@ -93,6 +297,23 @@ impl<'a> Encoder<'a> { pub fn new<'a>(wr: &'a mut io::Writer) -> Encoder<'a> { Encoder { wr: wr } } + + /// Encode the specified struct into a json [u8] + pub fn buffer_encode>>(to_encode_object: &T) -> ~[u8] { + //Serialize the object in a string using a writer + let mut m = MemWriter::new(); + { + let mut encoder = Encoder::new(&mut m as &mut io::Writer); + to_encode_object.encode(&mut encoder); + } + m.inner() + } + + /// Encode the specified struct into a json str + pub fn str_encode>>(to_encode_object: &T) -> ~str { + let buff:~[u8] = Encoder::buffer_encode(to_encode_object); + str::from_utf8_owned(buff) + } } impl<'a> serialize::Encoder for Encoder<'a> { From 339946cf2fa4510bfd15a8a9014477ede77d8134 Mon Sep 17 00:00:00 2001 From: musitdev Date: Sun, 19 Jan 2014 09:39:07 +0100 Subject: [PATCH 2/3] extra::json: add documentation and examples --- src/libextra/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libextra/json.rs b/src/libextra/json.rs index 88068f2cf7752..a56d840565f0f 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -306,7 +306,7 @@ impl<'a> Encoder<'a> { let mut encoder = Encoder::new(&mut m as &mut io::Writer); to_encode_object.encode(&mut encoder); } - m.inner() + m.unwrap() } /// Encode the specified struct into a json str From aeb541674cb97fdd68eacfda7309a06b39db7a83 Mon Sep 17 00:00:00 2001 From: musitdev Date: Sun, 19 Jan 2014 11:56:27 +0100 Subject: [PATCH 3/3] extra::json: add documentation and examples --- src/libextra/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libextra/json.rs b/src/libextra/json.rs index a56d840565f0f..76dc1d31c49b8 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -70,7 +70,7 @@ use extra::serialize::Encodable; fn main() { let to_encode_object = TestStruct{data_str:~"example of string to encode"}; - let mut m = io::mem::MemWriter::new(); + let mut m = io::MemWriter::new(); { let mut encoder = json::Encoder::new(&mut m as &mut std::io::Writer); to_encode_object.encode(&mut encoder);