In Godot 4.3 an array filled with integers in JSON will return looking like an array of integers.
I know that JSON does not distinguish between integers and floats. In Godot 4.4 my array of integers is converted into an array of floats.
Example:
{
“five”: [
7,
2,
3,
1,
6
]
}
loads into Godot as:
five: [7.0, 2.0, 3.0, 1.0, 6.0]
This means if I want to upgrade my game to 4.4 I have to find a way to convert a bunch of
values that had been working perfectly well. I tried to understand by reading a couple of git issues, but I still don’t really understand why this is better than leaving it the way it was
There’s a bit of a footgun there if you’re using integers as bit fields, though Godot’s handling of 64bit integers is kind of rough in that regard anyways.
It just means I have to go through the entire code base and find every place where I use it, or else do some sort of conversions when I fill my data store, which complicates the process. I didn’t see it listed as a major breaking change in the upgrade notes but it should be there.
I don’t really understand why turning all numbers into floats helps prevent bugs. Maybe an example would help me understand.
I think the problem is actually that JSON is actually kind of weak in the guarantees it offers for numbers. The JSON spec doesn’t differentiate between numbers that have fractional components and those which don’t. It also doesn’t differentiate between signed and unsigned values.
Unfortunately, with real hardware and fixed bitwidth representations of values, that means JSON has some sharp edges. A double and an int64_t have the same number of bits, but they spend them in different ways, and each has values that cannot be represented by the other. The floating point representation covers a wider set of magnitudes, but does so by throwing away precision at the low end. The integer values sacrifice range for precision at the high end, and (obviously) can’t represent non-integral values at all.
Since JSON has no in-spec method of tagging numeric values as anything other than “number”, it’s difficult to fix this for all cases. You could make everything strings ("uint32:0xDEADBEEF") and parse yourself, which actually wouldn’t be that much more expensive than the automatic stuff since it’s all parsed text anyways, but that’s obviously a pain in the ass too. I don’t think there are great answers here.
More recently, I’ve been seeing a move to things like CBOR, which have more precise ways of defining numeric types, don’t require as much runtime parsing, and are generally more compact. I’m not sure if Godot supports CBOR in any capacity, though.
The TL;DR here is: JSON kind of sucks for stuff like this and can’t be fixed. It’s convenient despite its weaknesses, but it’s always going to have tradeoffs. I do agree, however, that it sounds like the changes that were made were unnecessary and should have been listed as breaking; they will have improved things for some people and worsened things for others, because there’s no way of fixing the fundamental problems with JSON and have it still be JSON.
I think I’ve figured out how to switch to using typed arrays and dictionaries to force the conversion back to integer. I was worried it was going to require some really messy work around. It’s still definitely a breaking change, but I guess I can see how it’s hard to make choices about the best way to handle these issues. Thank you all for taking the time to help me.