The codec is designed for URI and URL components, as well as HTTP Request and Response payloads with the Content-Type
of application/x-www-form-urlencoded
.
Codec baseline
The baseline encoding method is Percent Encoding with adaptations for application/x-www-form-urlencoded
. Decoding follows the same process in reverse.
For application/x-www-form-urlencoded
, spaces ' '
are encoded as plus signns '+'
, newlines are encoded as '%0D%0A'
, and all characters except unreserved characters must be percent-encoded with in their UTF-8 representation.
Hierarchical and primitive values
Hierarchical data structures must be encoded into a single key=value
pair. This applies to all top-level values containing a data structure. The encoding involves representing a JSON object or array as a UTF-8 string.
Primitive values are encoded directly without converting to JSON.
Examples
{
response_type: "code",
scope: "openid",
client_id: "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r",
authorization_details: [{
type: "openid_credential",
format:"jwt_vc",
types:[
"VerifiableCredential",
"VerifiableAttestation",
"CTWalletInTime"
]
}],
redirect_uri: "openid:",
nonce: "glkFFoisdfEui43",
code_challenge: "YjI0ZTQ4NTBhMzJmMmZhNjZkZDFkYzVhNzlhNGMyZDdjZDlkMTM4YTY4NjcyMTA5M2Q2OWQ3YjNjOGJlZDBlMSAgLQo=",
code_challenge_method: "S256",
client_metadata: {
vp_formats_supported: {
jwt_vp: {
alg: ["ES256"]
},
jwt_vc: {
alg: ["ES256"]
}
},
response_types_supported: [
"vp_token",
"id_token"
],
authorization_endpoint: "openid:"
}
};
response_type=code
&scope=openid
&client_id=did%3Akey%3Az2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r
&authorization_details=%5B%7B%22type%22%3A%22openid_credential%22%2C%22format%22%3A%22jwt_vc%22%2C%22types%22%3A%5B%22VerifiableCredential%22%2C%22VerifiableAttestation%22%2C%22CTWalletInTime%22%5D%7D%5D
&redirect_uri=openid%3A
&nonce=glkFFoisdfEui43
&code_challenge=YjI0ZTQ4NTBhMzJmMmZhNjZkZDFkYzVhNzlhNGMyZDdjZDlkMTM4YTY4NjcyMTA5M2Q2OWQ3YjNjOGJlZDBlMSAgLQo%3D
&code_challenge_method=S256
&client_metadata=%7B%22vp_formats_supported%22%3A%7B%22jwt_vp%22%3A%7B%22alg%22%3A%5B%22ES256%22%5D%7D%2C%22jwt_vc%22%3A%7B%22alg%22%3A%5B%22ES256%22%5D%7D%7D%2C%22response_types_supported%22%3A%5B%22vp_token%22%2C%22id_token%22%5D%2C%22authorization_endpoint%22%3A%22openid%3A%22%7D
Encoding objects, arrays and primitives
{
obj: {
a: 1,
b: 2
},
arr: [ 1, 2, 3 ],
a: 1,
b: '2',
c: ' '
}
obj=%7B%22a%22%3A1%2C%22b%22%3A2%7D
&arr=%5B1%2C2%2C3%5D
&a=1
&b=2
&c=+
Javascript example
The URLSearchParams API can be used for application/x-www-form-urlencoded
. All top-level data structures must be JSON stringified in UTF-8 before encoding.
function jsonStringifyNotPrimitive([key, value]) {
if (value == null) {
// filter out null and undefined values
return null;
}
if (typeof value === "object") {
// this includes arrays
return [key, JSON.stringify(value)];
}
return [key, value];
}
function encodeObject(o) {
return new URLSearchParams(
Object.fromEntries(
Object.entries(o).map(jsonStringifyNotPrimitive).filter(Boolean),
),
).toString();
}
This function jsonStringifyNotPrimitive
ensures that objects and arrays are JSON stringified, while primitive values are encoded directly. The encodeObject
function then creates a URL-encoded string suitable for use in HTTP requests.