Recently, I was building an API endpoint that contained a field which could accept an arbitrary JSON payload. Anything from null
, to a simple object, to a deeply nested array.
While we weren't validating any of the contents of the field, we also didn't want to leave it completely open-ended in terms of size. We wanted to enforce a maximum payload size.
1MB seems like a reasonable limit, but how should we enforce it?
We couldn't use the typical max:1024
rule, because this wasn't a file upload. And we didn't want to validate number of characters or array elements.
The solution was to create a custom rule. Here's how I did it:
class MaximumJsonEncodedSize implements ValidationRule
{
public function __construct(protected int $maxSizeInKilobytes) {}
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (Str::length(json_encode($value)) > $this->maxSizeInKilobytes * 1024) {
$fail("The {$attribute} field must not be greater than {$this->maxSizeInKilobytes} kilobytes.");
}
}
}
In order to flatten the value out to a string, I used json_encode
. This will work for any value, including primitives, arrays and objects.
Technically, encoding adds characters to the payload, so the length calculation isn't 100% precise, but 1MB is such a high limit, it's just here as a sanity check.
I also use the exact validation error you would get if you used max
on a file upload field, just to keep things consistent.
Here to help,
Joel
P.S. I can't share a tip on validation without mentioning our book: Mastering Laravel Validation Rules.