{"id":17133782,"url":"https://github.com/slavikdev/jo","last_synced_at":"2026-02-12T18:31:18.838Z","repository":{"id":142155533,"uuid":"76388518","full_name":"slavikdev/jo","owner":"slavikdev","description":"Opinionated Go library to build RESTful JSON APIs.","archived":false,"fork":false,"pushed_at":"2016-12-22T23:11:28.000Z","size":70,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-04T18:38:45.576Z","etag":null,"topics":["framework","gin","go","golang","golang-library","json","json-api"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slavikdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-13T18:50:47.000Z","updated_at":"2019-06-06T06:01:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"282f3180-b335-4317-a37d-33499e5d6f13","html_url":"https://github.com/slavikdev/jo","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/slavikdev/jo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slavikdev%2Fjo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slavikdev%2Fjo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slavikdev%2Fjo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slavikdev%2Fjo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slavikdev","download_url":"https://codeload.github.com/slavikdev/jo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slavikdev%2Fjo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29376845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T18:17:34.915Z","status":"ssl_error","status_checked_at":"2026-02-12T18:17:34.495Z","response_time":55,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["framework","gin","go","golang","golang-library","json","json-api"],"created_at":"2024-10-14T19:43:01.534Z","updated_at":"2026-02-12T18:31:18.824Z","avatar_url":"https://github.com/slavikdev.png","language":"Go","readme":"# JO: Opinionated Go library to build RESTful JSON APIs.\n\nJo wraps around [gin](https://github.com/gin-gonic/gin) library and implements common patterns\nuseful in creating JSON APIs, such as strict response structure, authorization, logging, functional testing.\nBasically I've extracted all the stuff I usually add building APIs. It wouldn't fit\neveryone but that's exactly the point: to agree on common things once and use them as a framework.\nIf you need more flexibility–go get [gin](https://github.com/gin-gonic/gin).\n\n[![Travis Build Status](https://travis-ci.org/slavikdev/jo.svg)](https://travis-ci.org/slavikdev/jo)\n[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/h90m552en8cjxrv0?svg=true)](https://ci.appveyor.com/project/slavikdev/jo)\n[![codecov](https://codecov.io/gh/slavikdev/jo/branch/master/graph/badge.svg)](https://codecov.io/gh/slavikdev/jo)\n[![Go Report Card](https://goreportcard.com/badge/github.com/slavikdev/jo)](https://goreportcard.com/report/github.com/slavikdev/jo)\n[![GoDoc](https://godoc.org/github.com/slavikdev/jo?status.svg)](https://godoc.org/github.com/slavikdev/jo)\n[![Analytics](https://ga-beacon.appspot.com/UA-89293155-1/jo/readme?pixel)](https://github.com/igrigorik/ga-beacon)\n\n```go\nimport \"gopkg.in/slavikdev/jo.v1\"\n```\n\n## Example\n\n```go\npackage main\n\nimport (\n\t\"time\"\n\n\t\"gopkg.in/slavikdev/jo.v1\"\n)\n\nfunc main() {\n\t// Create api.\n\tapi := jo.NewAPI()\n\n\t// Map routes.\n\tapi.Map(\"get\", \"/time\", getTime)\n\tapi.Map(\"get\", \"/secret\", auth, getSecret)\n\n\t// Start api on port 9999.\n\terr := api.Run(\":9999\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\n// Returns successful response with current time in data field.\nfunc getTime(request *jo.Request) *jo.Response {\n\tcurrentTime := time.Now()\n\treturn jo.Ok(currentTime)\n}\n\n// Returns successful response with a word \"secret\" in data field.\nfunc getSecret(request *jo.Request) *jo.Response {\n\treturn jo.Ok(\"secret\")\n}\n\nconst apiToken string = \"0123456789\"\n\n// Checks if query string has apiToken argument with specific value.\n// If it does--passes request to next handler. Otherwise returns 403 Forbidden error.\nfunc auth(request *jo.Request) *jo.Response {\n\tif request.GetQuery(\"apiToken\") == apiToken {\n\t\treturn jo.Next(nil)\n\t}\n\treturn jo.Forbidden()\n}\n```\n\nThe example works as follows:\n```\nGET localhost:9999/time\n```\n```\nHTTP/1.1 200 OK\nContent-Type: application/json; charset=utf-8\nDate: Sun, 18 Dec 2016 00:51:43 GMT\nContent-Length: 64\n\n{\n    \"data\": \"2016-12-18T02:51:43.07980668+02:00\",\n    \"successful\": true\n}\n```\n\n```\nGET localhost:9999/secret\n```\n```\nHTTP/1.1 403 Forbidden\nContent-Type: application/json; charset=utf-8\nDate: Sun, 18 Dec 2016 00:51:10 GMT\nContent-Length: 88\n\n{\n    \"data\": null,\n    \"error\": {\n        \"code\": 403,\n        \"message\": \"Forbidden\",\n        \"data\": null\n    },\n    \"successful\": false\n}\n```\n\n```\nGET localhost:9999/secret?apiToken=0123456789\n```\n```\nHTTP/1.1 200 OK\nContent-Type: application/json; charset=utf-8\nDate: Sun, 18 Dec 2016 00:40:37 GMT\nContent-Length: 36\n\n{\n    \"data\": \"secret\",\n    \"successful\": true\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslavikdev%2Fjo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslavikdev%2Fjo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslavikdev%2Fjo/lists"}