Sane URL validation in JSON Schema
JSON Schema is a very useful tool for validating API requests. Sadly it’s not immune to the quagmire of pedantry that is URL validation.
Consider the following request payload.
{
"data": { "callbackUrl": "..." }
}
You may be tempted to validate this payload against the following JSON Schema.
{
"$id": "https://www.stephenlewis.me/nope.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": "data",
"properties": {
"data": {
"type": "object",
"required": "callbackUrl",
"properties": {
"callbackUrl": {
"type": "string",
"format": "uri"
}
}
}
}
}
This works fine, if you agree that dap://[2001:db8::7]/c=GB?objectClass?one
is a valid callback URL. I do not. I want something along the lines of https://www.example.com/endpoint
.
Here’s how to do that1.
{
"$id": "https://www.stephenlewis.me/sane-url.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": "data",
"properties": {
"data": {
"type": "object",
"required": "callbackUrl",
"properties": {
"callbackUrl": { "$ref": "#/definitions/saneUrl" }
}
}
},
"definitions": {
"saneUrl": { "format": "uri", "pattern": "^https?://" }
}
}
Scheme-less URLs
But what about “scheme-less” URLs, such as www.example.com
?
This is where JSON Schema comes up short. If you’re dealing with just a domain, and no path, the following definition covers the basics. It fails miserably on something like www.example.com/endpoint
, though.
{
"definitions": {
"plausibleUrl": {
"anyOf": [{ "$ref": "#/definitions/saneUrl" }, { "format": "hostname" }]
}
}
}
Either way, you’ll still need to do some manual validation.
Footnotes
-
Sort of. Madness such as
https://[a1:b2::c3]/omg=WHY
will still pass, so you may wish to perform further validation. ↩
Sign up for my newsletter
A monthly round-up of blog posts, projects, and internet oddments.