Here is a cute variant that doesn't need lzcnt nor tables, but only works up to 99,999:
(((x + 393206) & (x + 524188)) ^ ((x + 916504) & (x + 514288))) >> 17
This is for integer log 10, but could be adapted for number of digits. It needs a wrapper for 64 bit to invoke it multiple times, but most numbers in a JSON are small, so it might even be competitive; it needs only 4 cycles with enough instruction level parallelism.I gathered this idea from the output of a superoptimizer, it was fun to figure out how it works. For spoilers, see [1].
[1] https://github.com/rust-lang/rust/blob/master/library/core/s...