{"id":13413719,"url":"https://github.com/timsolov/rest-query-parser","last_synced_at":"2026-01-17T17:41:55.751Z","repository":{"id":40366440,"uuid":"239577156","full_name":"timsolov/rest-query-parser","owner":"timsolov","description":"Query Parser for REST","archived":false,"fork":false,"pushed_at":"2023-12-04T16:29:58.000Z","size":87,"stargazers_count":73,"open_issues_count":3,"forks_count":21,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-07-31T20:52:47.260Z","etag":null,"topics":["go","golang","orm","parse","parser","parsing","query","query-parser","rest","rest-api","restapi","sql"],"latest_commit_sha":null,"homepage":"","language":"Go","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/timsolov.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}},"created_at":"2020-02-10T17:58:42.000Z","updated_at":"2024-07-16T12:45:05.000Z","dependencies_parsed_at":"2024-01-30T06:01:13.217Z","dependency_job_id":null,"html_url":"https://github.com/timsolov/rest-query-parser","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timsolov%2Frest-query-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timsolov%2Frest-query-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timsolov%2Frest-query-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timsolov%2Frest-query-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timsolov","download_url":"https://codeload.github.com/timsolov/rest-query-parser/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243635799,"owners_count":20323000,"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":["go","golang","orm","parse","parser","parsing","query","query-parser","rest","rest-api","restapi","sql"],"created_at":"2024-07-30T20:01:47.351Z","updated_at":"2026-01-17T17:41:55.730Z","avatar_url":"https://github.com/timsolov.png","language":"Go","readme":"# Query Parser for REST\n\n\u003ca href=\"https://awesome-go.com/\"\u003e\u003cimg align=\"right\" src=\"https://github.com/avelino/awesome-go/raw/main/tmpl/assets/logo.png\" alt=\"awesome-go\" title=\"awesome-go\" /\u003e\u003c/a\u003e\n\n[![GoDoc](https://godoc.org/github.com/timsolov/rest-query-parser?status.png)](https://godoc.org/github.com/timsolov/rest-query-parser)\n[![Coverage Status](https://coveralls.io/repos/github/timsolov/rest-query-parser/badge.svg?branch=master)](https://coveralls.io/github/timsolov/rest-query-parser?branch=master)\n[![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome)\n\nQuery Parser is a library for easy building dynamic SQL queries to Database. It provides a simple API for web-applications which needs to do some filtering throught GET queries. It is a connector between the HTTP handler and the DB engine, and manages validations and translations for user inputs.\n\n\n\n## Installation\n    go get -u github.com/timsolov/rest-query-parser\n\n## Idea\n\nThe idia to write this library comes to me after reading this article: \n[REST API Design: Filtering, Sorting, and Pagination](https://www.moesif.com/blog/technical/api-design/REST-API-Design-Filtering-Sorting-and-Pagination/).\n\nAnd principles enumerated in article I considered very useful and practical to use in our project with amount of listings with different filtering.\n\n## Fast start\nSee cmd/main.go and tests for more examples.\n\n```go\n    package main\n    \n    import (\n        \"errors\"\n        \"fmt\"\n        \"net/url\"\n    \n        rqp \"github.com/timsolov/rest-query-parser\"\n    )\n    \n    func main() {\n        url, _ := url.Parse(\"http://localhost/?sort=name,-id\u0026limit=10\u0026id=1\u0026i[eq]=5\u0026s[eq]=one\u0026email[like]=*tim*|name[like]=*tim*\")\n        q, _ := rqp.NewParse(url.Query(), rqp.Validations{\n            \"limit:required\": rqp.MinMax(10, 100),  // limit must present in the Query part and must be between 10 and 100 (default: Min(1))\n            \"sort\":           rqp.In(\"id\", \"name\"), // sort could be or not in the query but if it is present it must be equal to \"in\" or \"name\"\n            \"s\":      rqp.In(\"one\", \"two\"), // filter: s - string and equal\n            \"id:int\": nil,                  // filter: id is integer without additional validation\n            \"i:int\": func(value interface{}) error { // filter: custom func for validating\n                if value.(int) \u003e 1 \u0026\u0026 value.(int) \u003c 10 {\n                    return nil\n                }\n                return errors.New(\"i: must be greater then 1 and lower then 10\")\n            },\n            \"email\": nil,\n            \"name\":  nil,\n        })\n\n        fmt.Println(q.SQL(\"table\")) // SELECT * FROM table WHERE id = ? AND i = ? AND s = ? AND (email LIKE ? OR name LIKE ?) ORDER BY name, id DESC LIMIT 10\n        fmt.Println(q.Where())      // id = ? AND i = ? AND s = ? AND (email LIKE ? OR name LIKE ?)\n        fmt.Println(q.Args())       // [1 5 one %tim% %tim%]\n\n        q.AddValidation(\"fields\", rqp.In(\"id\", \"name\"))\n        q.SetUrlString(\"http://localhost/?fields=id,name\u0026limit=10\")\n        q.Parse()\n\n        fmt.Println(q.SQL(\"table\")) // SELECT id, name FROM table ORDER BY id LIMIT 10\n        fmt.Println(q.Select())     // id, name\n        fmt.Println(q.Args())       // []\n    }\n```\n\n## Top level fields:\n* `fields` - fields for SELECT clause separated by comma (\",\") Eg. `\u0026fields=id,name`. If nothing provided will use \"\\*\" by default. Attention! If you want to use this filter you have to define validation func for it. Use `rqp.In(\"id\", \"name\")` func for limit fields for your query.\n* `sort` - sorting fields list separated by comma (\",\"). Must be validated too. Could include prefix +/- which means ASC/DESC sorting. Eg. `\u0026sort=+id,-name` will print `ORDER BY id, name  DESC`. You have to filter fields in this parameter by adding `rqp.In(\"id\", \"name\")`.\n* `limit` - is limit for LIMIT clause. Should be greater then 0 by default. Definition of the validation for `limit` is not required. But you may use `rqp.Max(100)` to limit top threshold.\n* `offset` - is offset for OFFSET clause. Should be greater then or equal to 0 by default. Definition of the validation for `offset` is not required.\n\n## Validation modificators:\n* `:required` - parameter is required. Must present in the query string. Raise error if not.\n* `:int` - parameter must be convertable to int type. Raise error if not.\n* `:bool` - parameter must be convertable to bool type. Raise error if not.\n\n## Supported types\n- `string` - the default type for all provided filters if not specified another. Could be compared by `eq, ne, gt, lt, gte, lte, like, ilike, nlike, nilike, in, nin, is, not` methods (`nlike, nilike` means `NOT LIKE, NOT ILIKE` respectively, `in, nin` means `IN, NOT IN` respectively, `is, not` for comparison to NULL `IS NULL, IS NOT NULL`).\n- `int` - integer type. Must be specified with tag \":int\". Could be compared by `eq, ne, gt, lt, gte, lte, in, nin` methods.\n- `bool` - boolean type. Must be specified with tag \":bool\". Could be compared by `eq` method.\n\n## Date usage\nThis is simple example to show logic which you can extend.\n\n```go\n    import (\n        \"fmt\"\n        \"net/url\"\n        validation \"github.com/go-ozzo/ozzo-validation/v4\"\n    )\n\n    func main() {\n        url, _ := url.Parse(\"http://localhost/?create_at[eq]=2020-10-02\")\n        q, _ := rqp.NewParse(url.Query(), rqp.Validations{\n            \"created_at\": func(v interface{}) error {\n                s, ok := v.(string)\n                if !ok {\n                    return rqp.ErrBadFormat\n                }\n                return validation.Validate(s, validation.Date(\"2006-01-02\"))\n            },\n        })\n\n        q.ReplaceNames(rqp.Replacer{\"created_at\": \"DATE(created_at)\"})\n\n        fmt.Println(q.SQL(\"table\")) // SELECT * FROM table WHERE DATE(created_at) = ?\n    }\n```","funding_links":[],"categories":["Query Language","查询语言","Go语言包管理","Relational Databases"],"sub_categories":["HTTP Clients","HTTP客户端","查询语"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimsolov%2Frest-query-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimsolov%2Frest-query-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimsolov%2Frest-query-parser/lists"}