{"id":15138388,"url":"https://github.com/zacharygolba/json-api-rs","last_synced_at":"2026-02-26T21:35:58.316Z","repository":{"id":62441380,"uuid":"106134973","full_name":"zacharygolba/json-api-rs","owner":"zacharygolba","description":"Idiomatic types for building a robust JSON API with Rust","archived":false,"fork":false,"pushed_at":"2018-05-27T20:53:41.000Z","size":144,"stargazers_count":26,"open_issues_count":3,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-30T19:07:30.915Z","etag":null,"topics":["json-api","rocket","rust","serde"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/json-api","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zacharygolba.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-07T22:34:22.000Z","updated_at":"2023-12-08T14:18:53.000Z","dependencies_parsed_at":"2022-11-01T22:01:42.074Z","dependency_job_id":null,"html_url":"https://github.com/zacharygolba/json-api-rs","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zacharygolba%2Fjson-api-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zacharygolba%2Fjson-api-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zacharygolba%2Fjson-api-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zacharygolba%2Fjson-api-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zacharygolba","download_url":"https://codeload.github.com/zacharygolba/json-api-rs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237843742,"owners_count":19375195,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json-api","rocket","rust","serde"],"created_at":"2024-09-26T07:23:05.866Z","updated_at":"2025-10-23T15:30:17.088Z","avatar_url":"https://github.com/zacharygolba.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# json-api\n\n[![CircleCI branch](https://img.shields.io/circleci/project/github/zacharygolba/json-api-rs/master.svg?style=flat-square)](https://circleci.com/gh/zacharygolba/json-api-rs/tree/master) [![AppVeyor branch](https://img.shields.io/appveyor/ci/zacharygolba/json-api-rs/master.svg?logo=appveyor\u0026style=flat-square)](https://ci.appveyor.com/project/zacharygolba/json-api-rs/branch/master) [![Codecov branch](https://img.shields.io/codecov/c/github/zacharygolba/json-api-rs/master.svg?style=flat-square)](https://codecov.io/gh/zacharygolba/json-api-rs) [![Crates.io](https://img.shields.io/crates/v/json-api.svg?style=flat-square)](https://crates.io/crates/json-api)\n\nIdiomatic types for building a robust [JSON API](http://jsonapi.org/).\n\n## Features\n\n### Serialization DSL\n\nYou can define a `Resource` using a friendly, declarative dsl.\n\n#### Concise\n\n```rust\n#[macro_use]\nextern crate json_api;\n\nstruct Post {\n    id: u64,\n    body: String,\n    title: String,\n    author: Option\u003cUser\u003e,\n    comments: Vec\u003cComment\u003e,\n}\n\nresource!(Post, |\u0026self| {\n    // Define the id.\n    id self.id;\n\n    // Define the resource \"type\"\n    kind \"posts\";\n\n    // Define attributes with a comma seperated list of field names.\n    attrs body, title;\n\n    // Define relationships with a comma seperated list of field names.\n    has_one author;\n    has_many comments;\n});\n```\n\n#### Flexible\n\n```rust\n#[macro_use]\nextern crate json_api;\n\nstruct Post {\n    id: u64,\n    body: String,\n    title: String,\n    author: Option\u003cUser\u003e,\n    comments: Vec\u003cComment\u003e,\n}\n\nresource!(Post, |\u0026self| {\n    kind \"articles\";\n    id self.id;\n\n    attrs body, title;\n\n    // Define a virtual attribute with an expression\n    attr \"preview\", {\n        self.body\n            .chars()\n            .take(140)\n            .collect::\u003cString\u003e()\n    }\n\n    // Define a relationship with granular detail\n    has_one \"author\", {\n        // Data for has one should be Option\u003c\u0026T\u003e where T: Resource\n        data self.author.as_ref();\n\n        // Define relationship links\n        link \"self\", format!(\"/articles/{}/relationships/author\", self.id);\n        link \"related\", format!(\"/articles/{}/author\", self.id);\n\n        // Define arbitrary meta members with a block expression\n        meta \"read-only\", true\n    }\n\n    // Define a relationship with granular detail\n    has_many \"comments\", {\n        // Data for has one should be an Iterator\u003cItem = \u0026T\u003e where T: Resource\n        data self.comments.iter();\n\n        // Define relationship links\n        link \"self\", format!(\"/articles/{}/relationships/comments\", self.id);\n        link \"related\", format!(\"/articles/{}/comments\", self.id);\n\n        // Define arbitrary meta members with a block expression\n        meta \"total\", {\n            self.comments.len()\n        }\n    }\n\n    // You can also define links with granular details as well\n    link \"self\", {\n        href format!(\"/articles/{}\", self.id);\n    }\n\n    // Define arbitrary meta members an expression\n    meta \"copyright\", self.author.as_ref().map(|user| {\n        format!(\"© 2017 {}\", user.full_name())\n    });\n});\n```\n\n### Rocket Support\n\nThe [json-api-rocket](https://crates.io/crates/json-api-rocket) crate provides responders\nas well as a fairing for catching errors and returning [JSON API](http://jsonapi.org)\nerror documents.\n\n```rust\n#![feature(plugin)]\n#![plugin(rocket_codegen)]\n\n#[macro_use]\nextern crate json_api;\nextern crate json_api_rocket;\nextern crate rocket;\n\nmod models;\n\nuse json_api_rocket::JsonApiFairing;\nuse json_api_rocket::response::{Collection, Member};\n\nuse models::Article;\n\n#[get(\"/\")]\nfn collection() -\u003e Collection\u003cArticle\u003e {\n    (1..25).map(Article::new).collect()\n}\n\n#[get(\"/\u003cid\u003e\")]\nfn member(id: u64) -\u003e Member\u003cArticle\u003e {\n    Member(Article::new(id))\n}\n\nfn main() {\n    rocket::ignite()\n        .attach(JsonApiFairing)\n        .mount(\"/articles\", routes![collection, member])\n        .launch();\n}\n\n```\n\n## License\n\nLicensed under either of\n\n* Apache License, Version 2.0\n  ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n* MIT license\n  ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n## Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzacharygolba%2Fjson-api-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzacharygolba%2Fjson-api-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzacharygolba%2Fjson-api-rs/lists"}