JSON building DSL and configurable serializers for Rust
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
tests
.gitignore
.travis.yml
CONTRIBUTING.md
Cargo.toml
LICENSE
Makefile
README.md

README.md

JsonWay

Build Status

JsonWay gives you a simple DSL for declaring JSON structures. This is particularly helpful when the generation process is fraught with conditionals and loops. It is inspired by jbuilder and has similar functionality.

# Cargo.toml
[dependencies.jsonway]
git = "https://github.com/rustless/jsonway"

API docs

Simple example

jsonway::object(|json| {
    json.set("first_name", "Luke".to_string());
    json.set("last_name", "Skywalker".to_string());

    json.object("info", |json| {
        json.set("homeworld", "Tatooine".to_string());
        json.set("born", "19 BBY".to_string());
        json.set("died", "Between 45 ABY and 137 ABY".to_string());
    });

    json.array("masters", |json| {
        json.push("Obi-Wan Kenobi".to_string());
        json.push("Yoda".to_string());
        json.push("Joruus C'baoth (Briefly)".to_string());
        json.push("Darth Sidious (Briefly)".to_string());
    });
});

// {
//   "first_name": "Luke",
//   "last_name": "Skywalker",
//   "info": {
//     "born": "19 BBY",
//     "died": "Between 45 ABY and 137 ABY",
//     "homeworld": "Tatooine"
//   },
//   "masters": [
//     "Obi-Wan Kenobi",
//     "Yoda",
//     "Joruus C'baoth (Briefly)",
//     "Darth Sidious (Briefly)"
//   ]
// }

Build with iterators

#[derive(Debug)]
enum Side {
    Light,
    Dark
}

struct Jedi {
    name: String,
    side: Side
}

let jedi = vec![
    Jedi { name: "Saes Rrogon".to_string(), side: Side::Dark },
    Jedi { name: "Qui-Gon Jinn".to_string(), side: Side::Light },
    Jedi { name: "Obi-Wan Kenobi".to_string(), side: Side::Light }
];

let light_jedi_objects_list = jsonway::array(|json| {
    // Use `objects` method to make list of objects
    json.objects(&mut jedi.iter(), |jedi, json| {
        match jedi.side {
            Side::Light => {
                json.set("name".to_string(), jedi.name.to_string());
                json.set("side".to_string(), format!("{:?}", jedi.side));
            }
            Side::Dark => json.skip(),
        }
    })
});

// [
//   {
//     "name": "Qui-Gon Jinn",
//     "side": "Light"
//   },
//   {
//     "name": "Obi-Wan Kenobi",
//     "side": "Light"
//   }
// ]

let light_jedi_tuple_list = jsonway::array(|json| {
    // Use `arrays` method to make list of lists
    json.arrays(&mut jedi.iter(), |jedi, json| {
        match jedi.side {
            Side::Light => {
                json.push(jedi.name.to_string());
                json.push(format!("{:?}", jedi.side));
            }
            Side::Dark => json.skip(),
        }
    })
});

// [
//   [
//     "Qui-Gon Jinn",
//     "Light"
//   ],
//   [
//     "Obi-Wan Kenobi",
//     "Light"
//   ]
// ]

You can explicitly make JsonWay object return null if you want:

// ..
match jedi.side {
    Side::Light => {
        json.push(jedi.name.to_string());
        json.push(format!("{:?}", jedi.side));
    },
    Side::Dark => json.null()
}

Serializers

Serializier

Provides convention and functionality to create custom JSON presenters for any struct.

use jsonway::{ObjectBuilder, Serializer};

struct Jedi {
    name: String
}

struct JediSerializer<'a> {
    jedi: &'a Jedi
}

impl<'a> Serializer for JediSerializer<'a> {
    fn root(&self) -> Option<&str> { Some("jedi") }
    fn build(&self, json: &mut ObjectBuilder) {
        json.set("name", self.jedi.name.to_string());
    }
}

let jedi = Jedi { name: "Saes Rrogon".to_string() };
let json = JediSerializer{jedi: &jedi}.serialize();

ObjectSerializer

ObjectSerializer<T> is a generic struct for single object:T serialization.

use jsonway::{ObjectBuilder, ObjectSerializer};

struct Jedi {
    name: String
}

struct JediSerializer;

impl ObjectSerializer<Jedi> for JediSerializer {
    fn root(&self) -> Option<&str> { Some("jedi") }
    fn build(&self, jedi: &Jedi, json: &mut ObjectBuilder) {
        json.set("name", jedi.name.to_string());
    }
}

let jedi = Jedi { name: "Saes Rrogon".to_string() };
let json = JediSerializer.serialize(&jedi);

ObjectScopeSerializer

ObjectScopeSerializer<T, S> is a generic struct for object:T and scope:S serialization.

use jsonway::{ObjectBuilder, ObjectScopeSerializer};

struct User {
    id: uint,
    is_admin: bool
}

struct Jedi {
    name: String,
    secret: String
}

struct JediSerializer;

impl ObjectScopeSerializer<Jedi, User> for JediSerializer {
    fn root(&self) -> Option<&str> { Some("jedi") }
    fn build(&self, jedi: &Jedi, current_user: &User, json: &mut ObjectBuilder) {
        json.set("name", jedi.name.to_string());

        if current_user.is_admin {
            json.set("secret", jedi.secret.to_string());
        }
    }
}

let jedi = Jedi {
    name: "Palpatine".to_string(),
    secret: "Dark side".to_string()
};
let current_user = User { id: 1, is_admin: true };
let json = JediSerializer.serialize(&jedi, &current_user);

ListSerializer

Provides convention and functionality to create custom JSON presenters for the list of resources including meta information.

TODO: Example