json-api

CircleCI branch AppVeyor branch Codecov branch Crates.io

Idiomatic types for building a robust JSON API.

⚠️ Warning

This crate is under active development. Some features have yet to be implemented, APIs are likely to change, and documentation is sparse.

Consider this alpha quality software until this warning is removed.

Features

Serialization DSL

You can define a Resource using a friendly, declarative dsl.

Concise

```rust pub struct Article { pub id: u64, pub body: String, pub title: String, pub author: User, pub comments: Vec, }

resource!(Article, |&self| { // Define the id with an expression that returns a string. id self.id.to_string();

// Define the resource "type"
kind "articles";

// Define attributes with a comma seperated list of field names.
attrs body, title;

// Define relationships with a comma seperated list of field names.
has_one author;
has_many comments;

}); ```

Flexible

```rust pub struct Article { pub id: u64, pub body: String, pub title: String, pub author: User, pub comments: Vec, }

resource!(Article, |&self| { // Define the id with an expression that returns a string. id self.id.to_string();

// Define the resource "type"
kind "articles";

// Define attributes with a comma seperated list of field names.
attrs body, title;

// Define a virtual attribute with a block expression
attr "preview", {
    self.body
        .iter()
        .cloned()
        .take(140)
        .collect::<String>()
}

// Define a relationship with granular detail
has_one "author", {
    // Data for has one should be Option<&T> where T: Resource
    data Some(&self.author);

    // Define relationship links
    link "self", format!("/articles/{}/relationships/author", self.id);
    link "related", format!("/articles/{}/author", self.id);

    // Define arbitrary meta members with a block expression
    meta "read-only", true
}

// Define a relationship with granular detail
has_many "comments", {
    // Data for has one should be an Iterator<Item = &T> where T: Resource
    data self.comments.iter();

    // Define relationship links
    link "self", format!("/articles/{}/relationships/comments", self.id);
    link "related", format!("/articles/{}/comments", self.id);

    // Define arbitrary meta members with a block expression
    meta "total", {
        self.comments.len()
    }
}

// You can also define links with granular details as well
link "self", {
    href format!("/articles/{}", self.id);
}

// Define arbitrary meta members with a block expression
meta "copyright", {
    format!("© 2017 {}", self.author.full_name())
}

}); ```

Rocket Support

The json-api-rocket crate provides responders as well as a fairing for catching errors and returning JSON API error documents.

```rust

![feature(plugin)]

![plugin(rocket_codegen)]

[macro_use]

extern crate jsonapi; extern crate jsonapi_rocket; extern crate rocket;

mod models;

use jsonapirocket::JsonApiFairing; use jsonapirocket::response::{Collection, Member};

use models::Article;

[get("/")]

fn collection() -> Collection

{ (1..25).map(Article::new).collect() }

[get("/")]

fn member(id: u64) -> Member

{ Member(Article::new(id)) }

fn main() { rocket::ignite() .attach(JsonApiFairing) .mount("/articles", routes![collection, member]) .launch(); }

```

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.