{"id":19346091,"url":"https://github.com/jsonurl/specification","last_synced_at":"2025-08-30T10:45:08.758Z","repository":{"id":103218126,"uuid":"247000564","full_name":"jsonurl/specification","owner":"jsonurl","description":"JSON-\u003eURL defines a text format for the JSON data model suitable for use within a URL/URI (as described by RFC3986). This repository holds the JSON-\u003eURL specification.","archived":false,"fork":false,"pushed_at":"2023-11-22T20:13:12.000Z","size":35,"stargazers_count":10,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-23T04:44:37.429Z","etag":null,"topics":["documentation","json","specification","specifications","uri","url"],"latest_commit_sha":null,"homepage":"http://www.jsonurl.org/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc-by-4.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jsonurl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-03-13T06:11:50.000Z","updated_at":"2025-04-22T04:15:38.000Z","dependencies_parsed_at":"2023-06-29T01:16:56.406Z","dependency_job_id":null,"html_url":"https://github.com/jsonurl/specification","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jsonurl/specification","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsonurl%2Fspecification","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsonurl%2Fspecification/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsonurl%2Fspecification/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsonurl%2Fspecification/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jsonurl","download_url":"https://codeload.github.com/jsonurl/specification/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsonurl%2Fspecification/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272839675,"owners_count":25001862,"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","status":"online","status_checked_at":"2025-08-30T02:00:09.474Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["documentation","json","specification","specifications","uri","url"],"created_at":"2024-11-10T04:08:54.814Z","updated_at":"2025-08-30T10:45:08.720Z","avatar_url":"https://github.com/jsonurl.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# 1. About\n[RFC8259][1] describes the JSON interchange format, which is widely used in\napplication-level protocols including RESTful APIs. It is common for\napplications to request resources via the HTTP POST method with JSON entities\nbecause, per RFC7231\n[Section 4.3.1](https://tools.ietf.org/html/rfc7231#section-4.3.1):\n\n    A payload within a GET request message has no defined semantics;\n    sending a payload body on a GET request might cause some existing\n    implementations to reject the request.\n \nHowever, POST is suboptimal for requests which do not modify a resource's\nstate because it is not idempotent and limits or prevents client caching.\n\nWhile one could simply [percent encode][8] JSON text such that it's suitable\nfor inclusion in an HTTP GET request, anything other than a trivial payload\nwould be difficult for a human to read or modify; that's presumably why it's\nnot often done in practice.  Alternatively, one could use something other than\nJSON, however, there's good reason to choose JSON. It defines a simple but\npowerful data model, and it's very well known.\n\nJSON\u0026#x2192;URL defines a text format for the JSON data model suitable for\nuse within a [URL][10]/[URI][4].\n\n## 1.1 Terminology\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\",\n\"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"NOT RECOMMENDED\", \"MAY\", and\n\"OPTIONAL\" in this document are to be interpreted as described in\n[RFC2119][3] when, and only when, they appear in all capitals, as shown here.\n   \nThe terms \"JSON text\", \"value\", \"object\", \"array\", \"number\", \"string\",\n\"name\", and \"member\" in this document are to be interpreted as described\nin [RFC8259][1].\n\n## 1.2 Requirements Notation\nThis document uses the Augmented Backus-Naur Form (ABNF) notation described\nin [RFC5234][2].\n\n## 1.3 Latest Version\nThe latest version of this document may be found here:\nhttps://github.com/jsonurl/specification/\n\n\n# 2. Grammar\n[RFC8259][1] describes the JSON data model, which includes objects, arrays,\nand value literals. This document defines a new grammar for the JSON data\nmodel called JSON\u0026#x2192;URL. It also borrows heavily from RFC8259 so\nit's recommended that you read it first.\n\nJSON\u0026#x2192;URL text is a sequence of characters as defined by\n[RFC3986, section 2][9]. Encoded octets MUST be UTF-8 encoded UNICODE\ncodepoints. JSON\u0026#x2192;URL text complies with [RFC3986, section 3.4][7] and\nis suitable for use as a URI query string.\n\nLike JSON text, JSON\u0026#x2192;URL text is also a sequence of tokens. The set of\ntokens includes structural characters, strings, numbers, and three literal\nnames.\n\n\tJSON-URL-text = value\n\nThese are the four structural characters:\n\n\tbegin-composite    = %x28  ; ( left paren\n\tend-composite      = %x29  ; ) right paren\n\tname-separator     = %x3A  ; : colon\n\tvalue-separator    = %x2C  ; , comma\n\nNote that while RFC8259 defines one set of tokens for arrays and another set\nfor objects JSON\u0026#x2192;URL defines only a single set for both arrays and\nobjects. This change is due to the limitations imposed by the `query`\nproduction defined in [RFC3986][5]. With one exception arrays and objects are\nsemantically no different here than in RFC8259 -- it's simply the grammar\nthat's different. A lookahead token will allow a JSON\u0026#x2192;URL parser to\ndistinguish between arrays and objects in all cases except when the object or\narray has no members.\n\nWhitespace MUST NOT be used.\n\n## 2.1 Values\nA JSON\u0026#x2192;URL value MUST be a composite, number, string, or one of three\nliteral names. The three literals and the number production are defined\nexactly as in RFC8259. Object, array, and string are defined in the\nfollowing sections of this document.\n\n\tvalue = false / null / true / composite / number / string\n\t\n## 2.2 Composites\nA composite value is an array, object, or the `empty-composite` value\nwhich represents an array/object with no members. In JSON\u0026#x2192;URL, an\nempty array and empty object are indistinguishable. This constitutes the\nonly difference between the data model defined in this document and\nRFC8259.\n\n\tcomposite       = empty-composite / object / array\n\tempty-composite = begin-composite end-composite ; ()\n\n## 2.3 Objects\nAn object structure is represented as a pair of parentheses surrounding one\nor more name/value pairs (or members). A name is a string. A single colon\ncomes after each name, separating the name from the value. A single comma\nseparates a value from a following name.\n\n\tobject = begin-composite member *( value-separator member ) end-composite\n\tmember = string name-separator value\n\n## 2.4 Arrays\nAn array structure is represented as a pair of parentheses surrounding one\nor more values. Multiple values are separated by commas.\n\n\tarray = begin-composite value *( value-separator value ) end-composite\n\nAs in RFC8259 there is no requirement that the values in an array be of the\nsame type.\n\n## 2.5 Strings\nThough semantically equivalent to `string` as defined in RFC8259\nthe grammar for a JSON\u0026#x2192;URL string is quite different. A JSON\u0026#x2192;URL\nstring MAY be surrounded by single-quotes (a.k.a. apostrophes), however, it is\nonly necessary to do so when the value would be otherwise ambiguous. In\npractice, this means single quotes MUST be used to represent a string literal\n'true', 'false', 'null', or number. Otherwise, their use is OPTIONAL. Object\nkeys are always assumed to be strings and need not be quoted even if they\nwould otherwise be interpreted as a Number, Boolean, or `null`.\n\nWhen used in a string literal a `plus` character (U+002B) represents a single\nspace character (U+0020) just like the [x-www-form-urlencoded][6] type.\n\nAll text must comply with the `query` production defined in [RFC3986][7],\nsection 3.4. Therefore, any characters outside the set of allowed literal\ncharacters MUST be [percent encoded][8].\n\nThere is a meaningful difference between a structural character and an encoded\nstructural character. When encoded, a parser MUST interpret the character\nas part of a string literal. When not encoded the character retains its\nstructural meaning. Quoted strings need not encode structural characters.\n\n    string        = uchar *(uchar / apos) ; unquoted string\n                  / apos *qchar apos      ; quoted string\n    \n    uchar         = unencoded / pct-encoded / space-encoded\n    \n    qchar         = uchar / struct-char\n    \n    unencoded     = digit\n                  / %x41-5A            ; A-Z  uppercase letters\n                  / %x61-7A            ; a-z  lowercase letters\n                  / %x2D               ; -    dash\n                  / %x2E               ; .    period\n                  / %x5F               ; _    underscore\n                  / %x7E               ; ~    tilde\n                  / %x21               ; !    exclamation point\n                  / %x24               ; $    dollar sign\n                  / %x2A               ; *    asterisk\n                  / %x2F               ; /    solidus\n                  / %x3B               ; ;    semicolon\n                  / %x3F               ; ?    question mark\n                  / %x40               ; @    at sign\n                  \n    apos          = %x27               ; '    single quote/apostrophe\n    \n    struct-char   = %x28               ; (    open paren\n                  / %x29               ; )    close paren\n                  / %x2C               ; ,    comma\n                  / %x3A               ; :    colon\n\t\n    pct-encoded   = %x25 hexdig hexdig ; %XX  percent encoded\n\t\n    space-encoded = %x2B               ; +    plus sign\n    \n    hexdig        = digit / %x41-46    ; A-F  hexadecimal digits\n    digit         = %x30-39            ; 0-9  digits\n\n## 2.6 Numbers\nNumbers are represented exactly as defined in RFC8259, Section 6. Note that\nwhen used in a number the `plus` character (U+002B) is literal and MUST NOT\nbe interpreted by a JSON\u0026#x2192;URL parser as a space character (as it would be\nin a string literal).\n\n## 2.7 Whitespace\nThe grammar defined in RFC8259 allows for \"insignificant whitespace\" as it\ncan make it easier for the human eye to parse JSON text. However,\nunescaped whitespace is not allowed in a URL and escaped whitespace would\nlikely make it more difficult for the human eye to parse.  Therefore,\nunescaped whitespace MUST NOT be present in JSON\u0026#x2192;URL text. Escaped\nwhitespace MAY be present, however, it is always considered significant.\n\n## 2.8 x-www-form-urlencoded\nJSON\u0026#x2192;URL text is designed to play well with [x-www-form-urlencoded][6]\ndata. JSON\u0026#x2192;URL text MUST percent-encode literal `\u0026` and `=` characters.\nThis allows one or more traditional HTML form variables to be standalone\nJSON\u0026#x2192;URL text.\n\n## 2.9 Optional Syntaxes\nA JSON\u0026#x2192;URL parser implementation MAY support additional syntax options.\nImplementations SHOULD default to the grammar described above and only allow\nan alternate syntax when explicitly enabled. Each section defines a syntax\noption as a modification of previously defined grammar productions and/or\ndefinition of new ones.\n\n### 2.9.1 Implied Arrays\nIf both a sender and its receiver agree a priori that the top-level value is an\narray then a parser MAY accept JSON\u0026#x2192;URL text that omits the first\n`begin-composite` and last `end-composite` characters.\n\n    implied-array = [value] *( value-separator value )\n\nNote that, unlike an `array`, an `implied-array` may be empty (i.e. contain\nzero values). There is no ambiguity in this case and the parse result MAY be an\narray rather than the `empty-composite`.\n\n`implied-array` is OPTIONAL. A JSON\u0026#x2192;URL parser is not required to\nsupport it.\n\n### 2.9.2 Implied Objects\nIf both a sender and its receiver agree a priori that the top-level value is an\nobject then a parser MAY accept JSON\u0026#x2192;URL text that omits the first\n`begin-composite` and last `end-composite` characters.\n\n    implied-object = [member] *( value-separator member )\n\nNote that, unlike an `object`, an `implied-object` may be empty (i.e. contain\nzero members). There is no ambiguity in this case and the parse result MAY be an\nobject rather than the `empty-composite`.\n\n`implied-object` is OPTIONAL. A JSON\u0026#x2192;URL parser is not required to\nsupport it.\n\n### 2.9.3 x-www-form-urlencoded Arrays and Objects\nA parser MAY accept x-www-form-urlencoded style separators as structural\ncharacters for a top-level array or object.\n\n    wfu-name-separator      = %x3D  ; = equal \n    wfu-value-separator     = %x26  ; \u0026 ampersand\n    \n    wfu-composite           = empty-composite / wfu-object / wfu-array\n\n    wfu-object = begin-composite wfu-member *( wfu-value-separator wfu-member ) end-composite\n    wfu-member = string wfu-name-separator value\n    \n    wfu-array  = begin-composite value *( wfu-value-separator value ) end-composite\n\nThis may be combined with an implied array or object to form a URL query\nstring that is a syntactically valid, traditional HTML form data query\nstring.\n\n    wfu-implied-composite = wfu-implied-object / wfu-implied-array\n\n    wfu-implied-object    = [wfu-member] *( wfu-value-separator wfu-member )\n    \n    wfu-implied-array     = [value] *( wfu-value-separator value )\n\nNote that `wfu-composite` and `wfu-implied-composite` indirectly reference\n`qchar`, which allows unencoded literal `,` and `:` characters but requires\nliteral `\u0026` and `=` characters to be encoded. This is intentional, and allows\nJSON\u0026#x2192;URL text to meet the goal outlined in section 2.7.  \n\n`wfu-composite` and `wfu-implied-composite` are OPTIONAL. A JSON\u0026#x2192;URL\nparser is not required to support them.\n\n### 2.9.4 Implied Object Missing Values\nIf a parser supports `implied-object` and/or `wfu-implied-object` then it MAY\naccept JSON\u0026#x2192;URL text where values (and their respective name-separators)\nare omitted for the top-level implied object.\n\n    mv-implied-object = [mv-member] *( value-separator mv-member )\n    mv-member = string [name-separator value]\n\n    mv-wfu-implied-object = [wfu-member] *( wfu-value-separator wfu-member )\n    mv-wfu-member = string [wfu-name-separator value]\n\n`mv-implied-object` and `mv-wfu-implied-object` are OPTIONAL. A\nJSON\u0026#x2192;URL parser is not required to support them. A JSON\u0026#x2192;URL\nparser implementation SHOULD provide a mechanism which allows the caller to\nsupply a default value.\n\n### 2.9.5 Empty Objects and Arrays\nSection 2.2 defines the empty composite and outlines that there is no\ndistinction between an empty object and empty array. A parser MAY\ndistinguish between the two by defining `composite` as follows.\n\n    composite       = empty-object / empty-array / object / array\n    empty-array     = begin-composite end-composite ; ()\n    empty-object    = begin-composite name-separator end-composite ; (:)\n\n### 2.9.6 Address Bar Query String Friendly\nA web browser address bar will often percent encode characters even when it's\nnot necessary to do so. In particular, apostrophes are encoded despite\nthe fact that they are identified by RFC3986 as `sub-delims`. This\ninterferes with the JSON\u0026#x2192;URL string encoding strategy outlined above.\nThere can't be a meaningful difference between `'` and `%x27` if the browser\nchanges one to the other at its own discretion.\n\nThe address bar query string friendly (AQF) syntax allows JSON\u0026#x2192;URL\nto work in this context. It relies on escaping rather than encoding (or\nquoting) to distinguish between characters that are part of a string\nand characters that are structural or form one of the other literal values.\nExcept for ampersand (`%x26`), equals (`%x3D`), and plus (`%x2B`),\na parser MUST decode each UNICODE codepoint before it's evaluated, which will\nensure the browser's encoding preferences do not affect how a a JSON\u0026#x2192;URL\nparser interprets the character sequence.\n\nThe AQF syntax modifies the `string` production as follows.\n\n    string    = 1*char\n    \n    char      = uchar / apos / esc-seq\n    \n    esc-seq   = escape eval\n    \n    escape    = %x21               ; !\n    \n    eval      = struct-char\n              / digit\n              / %x2B               ; +    plus\n              / %x2D               ; -    dash\n              / %x21               ; !    exclamation point\n              / %x65               ; e    the empty string\n              / %x66               ; f    lowercase f\n              / %x6E               ; n    lowercase n\n              / %x74               ; t    lowercase t\n\nAn escape sequence begins with an exclamation point and MUST be following by\nanother character, the escape value. The set of valid escape values is\ndefined by `eval`.\n\n* Structural characters MUST be escaped when used in a string.\n* A leading digit or dash MUST be escaped in a string that would otherwise\nbe interpreted as a number. Non-leading digits or dash MAY be escaped but\nthere is no benefit in doing so.\n* A plus MUST be escaped\n* Exclamation point itself MUST be escaped\n* A leading lowercase `f` MUST be escaped in a string that would otherwise\nbe interpreted as `false`.\n* A leading lowercase `n` MUST be escaped in a string that would otherwise\nbe interpreted as `null`.\n* A leading lowercase `t` MUST be escaped in a string that would otherwise\nbe interpreted as `true.`\n* The empty string MUST be represented as `!e`\n\nNote that, like any other octet, the exclamation point escape character itself\nand/or `eval` may be percent encoded.\n\nBecause browsers do recognize a meaningful difference between literal and\nencoded ampersand and equals, when used in a query string, the AQF syntax\nretains that distinction. This allows for it to continue to work with\nx-www-form-urlencoded arrays and objects.\n\nThe AQF syntax is OPTIONAL. A JSON\u0026#x2192;URL parser is not required to\nsupport it.\n\n# 3. Examples\nHere are a few examples.\n## 3.1 String Literal\nHere are some string literals:\n\n    word\n    two+words\n    Hello%2C+World!\n    'Hello,+World!'\n    'true'\n    '42'\n\n## 3.2 Number Literal\nHere are some number literals:\n\n    0\n    1.0\n    1e2\n    -3e4\n    42\n\n## 3.3 Object\nHere are some objects:\n\n    (key:value)\n    (Hello:World!)\n    (key:value,nested:(key:value))\n\n## 3.4 Array\nHere are some arrays:\n\n    (1)\n    (1,2,3)\n    (a,b,c)\n    (a,b,(nested,array))\n    (array,of,objects,(object:1),(object:2))\n    \n## 3.5 Implied Array\nHere are some implied arrays:\n\n    1\n    1,2,3\n    a,b,c\n    a,b,(nested,array)\n    array,with,objects,(object:1),(object:2)\n\n## 3.6 Implied Object\nHere are some implied objects:\n\n    key:value\n    Hello:World!\n    key:value,nested:(key:value)\n\n## 3.7 x-www-form-urlencoded Implied Array\nHere are some implied arrays that make use of x-www-form-urlencoded style\nseparators:\n\n    1\n    1\u00262\u00263\n    a\u0026b\u0026c\n    a\u0026b\u0026(nested,array)\n    array\u0026with\u0026objects\u0026(object:1)\u0026(object:2)\n    \n## 3.8 x-www-form-urlencoded Implied Object\nHere are some implied objects that make use of x-www-form-urlencoded style\nseparators:\n\n    key=value\n    Hello=World!\n    key=value\u0026nested=(key:value)\n\n## 3.9 Implied Object With Missing Values\nHere are some implied objects with missing values:\n\n    key\n    key,Hello=World!\n    key=value\u0026marker\u0026nested=(key:value)\n    \n## 3.9 Address Bar Query String Friendly\nHere are some AQF values:\n\n    (Hello:World!!)\n    (key:value,strings:(a,!true,c,!3.14,!-5))\n    (1,2,3,Hello!,+World!!)\n    (a,!e,c)\n\n[1]: https://tools.ietf.org/html/rfc8259        \"RFC8259\"\n[2]: https://tools.ietf.org/html/rfc5234        \"RFC5234\"\n[3]: https://tools.ietf.org/html/rfc2119        \"RFC2119\"\n[4]: https://tools.ietf.org/html/rfc3986        \"RFC3986\"\n[5]: https://tools.ietf.org/html/rfc3986#appendix-A \"RFC3986, Appendix A.\"\n[6]: https://en.wikipedia.org/wiki/Percent-encoding#The_application.2Fx-www-form-urlencoded_type \"application/x-www-form-urlencoded\"\n[7]: https://tools.ietf.org/html/rfc3986#section-3.4 \"RFC3986, Section 3.4.\"\n[8]: https://tools.ietf.org/html/rfc3986#section-2.1 \"RFC3986, Section 2.1.\"\n[9]: https://tools.ietf.org/html/rfc3986#section-2 \"RFC3986, Section 2.\"\n[10]: https://tools.ietf.org/html/rfc1738        \"RFC1738\"\n[11]: https://tools.ietf.org/html/rfc8259#section-6 \"RFC8259, Section 6.\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsonurl%2Fspecification","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsonurl%2Fspecification","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsonurl%2Fspecification/lists"}