Ah, okay, yeah, thinking about it, that makes sense, I guess. JSON itself doesn't really make any distinction between integers and floats, it just has a generic "number" data type. (Which is technically not even a float, but a real number of arbitrary precision.)
So when Godot loads a dictionary from a JSON, it can't really say if it originally was an integer or a float, so I guess it just makes it all floats as a compromise. It could do some semi-intelligent heuristics, like if it does have something behind the decimal point, make it a float, but then the question would be, what to do with Arrays. You could maybe check all values in the Array, but that all gets ugly fast.
A different solution would be to, maybe, have an additionally type dict in there as well, which maps names (or "paths", if you will) to explicit type, and handle that automatically on serialization/deserialization. But that of course makes it more complex as well, and cuts down on thethe easy editable nature of JSON. Or have each value be a dict with explict type information, but that too sacrifices the human-readability.
So I assume that's the compromise they made: numbers in save data will fold to float on save/load.