Why have numbers, true, false or null then? Why not only support strings?
{"foo": "2", "bar": "null", "baz": "false"}
I’m not really being facetious: that’s what canonical s-expressions did: ((foo 2) (bar null) (baz false))
Type declarations can imply syntax, semantics or both.
Yes, you could represent everything as a string; in that case, the serialization format is no longer providing any assistance in verifying or enforcing syntax.
But it’s often useful to be able to verify syntax independently. And it helps avoid authoring errors (like using “1” instead of “true” etc.) that are ambiguous if your only hint is semantic.
It's of course a trade-off in how far you want to go with special types.
Booleans and numbers have extremely common use cases, moreso than date/times.
But perhaps more importantly, they are quite easy to define. Date/time is a susprisingly complex topic with many variants (date, time, datetime, local/relative date/time, point in time, offset-based, timezone-based...) with all of them being quite important. The spec to define date/time types would likely be longer than for the whole rest of JSON, and you still wouldn't be able to correctly interpret the date/time from the spec alone, since timezone data/designations are dynamic.
Now the question is - what value does this extra complexity bring? I'm not saying there isn't any, but it doesn't seem to justify the cost.