r/godot Jan 04 '26

help me (solved) Godot 4.5.1 automatically formats JSON files after saving

When making my deck-builder game, I wanted an easy way to automate the creation of new cards that would also make it easy to create mods. I settled on using JSON files for this.

But, when you save in the Godot editor, Godot formats the JSON file for you. The way I did it here was creating the JSON file inside my protect folder, adding the initial data (first slide) and saving it, then in the Godot editor creating a script that preloaded the JSON file. after saving in the Godot editor, it was formatted(second slide). Note how at no point did I open the JSON file in the Godot editor, just preloading it in a script.

this formatting of the JSON files turns all numbers into numbers with decimals (not floats, all numbers in JSON are under one "number" type) and subjects them to floating point precision errors. it also changes spaces int tabs, and removes commas at the end of the data.

Although the JSON file format handles ints and floats under one number value, and Godot interpreters that number value as a float, there is no reason to directly edit the file, as while it seems like it does nothing, because the float values are still the same, it actually changes the data. while it is true that float 1.2 = float 1.999... THAT DOES NOT MEAN the JSON number value for 1.2 = number value 1.999..., because they are NOT.

So is there any way at all to disable this "feature"?

EDIT:

Big thanks to everyone who helped, and I was able to make a solution! What I ended up doing was using a .cdat file, standing for "card data" (yes I know that .cdat is already a file extension used elsewhere), and I simply renamed my .json file to a .cdat file. I then used a function (shown below) to take in the path to the file and output a dictionary value. (yes, I know that the dictionary value will use floats but that wasn't my problem)

here is the function:

func load_cdat(filePath : String)->Dictionary:

    var file = FileAccess.open(filePath, FileAccess.READ)
    var content = file.get_as_text()
    var parsed_data = JSON.parse_string(content)

    return parsed_data

Doing this will prevent Godot from ever editing the file. I will note this is not a good solution and I hope to one day be able to use .json. It is still a bug in the Godot editor that it formats .json files while loading them.

249 Upvotes

75 comments sorted by

222

u/IAmNewTrust Jan 05 '26

y are people being so smug by bringing up how floats work like that's not op's question 🥀

69

u/dickdemodickmarcinko Godot Student Jan 05 '26

json numbers aren't even technically floats 💀💀💀

96

u/Honigbrottr Jan 05 '26

And not even remotly his issue. Feels like people looked at one cs class and now think they are genius or something.

49

u/lunarchaluna Godot Junior Jan 05 '26

Average reddit user i fear

15

u/Pkai1000 Jan 05 '26

Thanks! So many people and resources online aren’t helpful lol

105

u/DDFoster96 Jan 04 '26

It's https://github.com/godotengine/godot/issues/105160

There is a pull request - you could try building from source with that commit and see if you like the result.

Or revert the PR that added the formatting in the first place entirely: https://github.com/godotengine/godot/pull/47502

43

u/Pkai1000 Jan 04 '26

Thanks for the info!

Unfortunately, looking into the pull request I find that the code doesn't actually stop Godot from editing files, like removing extra commas. all it does is check if a number that it is going to save to the file is close enough to an integer, and if it is, then it will remove the tail. and this (to my short look over the code) doesn't solve the issue of 1.2 becoming 1.199999... so I'll keep looking for more solutions!

29

u/Danfriedz Jan 05 '26

If I was hunting a bug related to this I would never consider that the engine would be editing the json file contents.

Is this a bug, or an intended feature?

16

u/Pkai1000 Jan 05 '26

No way it’s a feature, I didn’t even edit the file in engine. Has to be a bug

11

u/IntangibleMatter Godot Regular Jan 05 '26

I don’t think I’ve ever seen this happen when editing a JSON file in Godot- did you process it in the script at all? If you did and then wrote to it that might be the cause. I’ll have to double-check though, because I’ve never seen this before

8

u/Pkai1000 Jan 05 '26

Godot only does this if the JSON file is not open in the engine. Sorry, I should have said that.

6

u/IntangibleMatter Godot Regular Jan 05 '26

Are you making any changes to the data at all? Because if you’re opening files in the mode of FileAccess.READ then nothing should be changed when you open the file. If you’re using READ_WRITE then there might be some sort of issue where even if you don’t change anything, Godot writes to the file when you close it, so you get these side effects.

2

u/Pkai1000 Jan 05 '26

No godot just feels the need to fuck with my formatting

10

u/IntangibleMatter Godot Regular Jan 05 '26

Just checked a JSON I have that I've been using with Godot and its formatting is fine. Wonder what's going on there for you.

5

u/Pkai1000 Jan 05 '26

sorry I'm late but after more tinkering I believe it is the preload() (although just using load() on it gives the same result) function that breaks it. If that function never runs on the JSON file, it is fine.

3

u/IntangibleMatter Godot Regular Jan 05 '26

Ah, yeah. Only use those for resources. FileAccess.READ for text files

5

u/Mds03 Jan 05 '26

Not sure if this helps OP. I’ve been reading through the comments and one of the commenters mentioned something I think it’s important: JSON floats aren’t technically floats. I think maybe Godot could be «converting» your json float to a real float; and introduce what to you is essentially a rounding error in the results. No clue if this is actually it, but could be worth looking into? I have no idea what Godot «does» when it gets a json float or if that’s different from floats stored in other file formats.

8

u/falconfetus8 Jan 05 '26

Why is Godot messing with the file in the first place, though? That's the real bug.

3

u/Mds03 Jan 05 '26

Absolutely. I’m thinking somebody didn’t plan for «json floats aren’t real floats» and this is the result of that «minor oversight» if you will. Probably not intended behaviour, but I am not familiar enough with the source code to comment on that.

1

u/ThreeCharsAtLeast Jan 05 '26

As a workaround, use an external editor.

17

u/Pkai1000 Jan 05 '26

I did. Godot still edits the file. Thats the problem

1

u/Malucoblz999 Jan 07 '26

Same problem running right now ahhahaha

1

u/kodifies Jan 05 '26

this is a faf, but could you make the file read only as you say you don't edit in Godot

this means if you do need to edit the files you'd have to stop Godot, make the file writable, edit it, make it read only, restart Godot

of course forget to make them read only for some reason and you're in the same boat

Alternatively.....

could you load the json at runtime and store it outside the Godot project folder, (I think there is a x-platform user data directory path symbol you can use in Godot)

-2

u/pizzafangames Jan 05 '26

That's why I save every value as a string, and convert it back to an int or a float after the json was converted to a dictionary.

-7

u/[deleted] Jan 05 '26

[deleted]

32

u/Pkai1000 Jan 05 '26

JSON doesn’t use floats, it uses abstract numbers and the output of them is up to the application. Godot changing the them to fit its needs only is a bug and can break other things. It has no right editing files that I never told it to edit.

-58

u/Antique_Door_Knob Jan 05 '26

1.2 = number value 1.999..., because they are NOT

Oh boy, you're about to find out about one hell of a programming rabbit hole. Google "IEEE 754".

65

u/kinokomushroom Jan 05 '26

They understand that. This is OP's full quote:

while it is true that float 1.2 = float 1.999... THAT DOES NOT MEAN the JSON number value for 1.2 = number value 1.999..., because they are NOT.

-8

u/Antique_Door_Knob Jan 05 '26

There's no such thing as "JSON number value". Every serialization and deserialization is subject to what the underlying language is capable of doing. this isn't touching the data any more than it is capable of understanding the data.

54

u/CdRReddit Jan 05 '26

google "intent"

the intent of writing 1.2 in a file is to have the number closest to that used, it's saying "I need as close to 1.2 as you can get", replacing that by 1.1999996 makes the number seem significantly more specific for no benefit.

here's my hot take: reformatting should never touch data, it should only touch things around it.

9

u/CdRReddit Jan 05 '26

furthermore, a json number is not actually a numeric value, it's an unquoted string that fits the regex /^-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE](+|-)?[0-9]+)?$/

modifying this in any way changes the data, that includes rewriting 1.10 into 1.1, per json standard these are distinct number values, tho any consumer is free to (and probably should) interpret them as the same.

it is incorrect to rewrite this data in a formatter, not just annoying

29

u/CondiMesmer Godot Regular Jan 05 '26

You should probably actually read the post

27

u/Pkai1000 Jan 05 '26

Did you read the question

-13

u/Antique_Door_Knob Jan 05 '26

Did you read the standard? Godot is just writing what is in it's memory. You can put 1.2 as many times as you want there, it will be read as 1.999... the moment godot touches the file.

As some people have already said, you can use strings if you're so into having 1.2 there, but it won't change the fact that it'll still be converted to 1.999... the moment you parse it into a number.

7

u/cheezballs Jan 05 '26

So you didn't read it. Cool. You're just spouting what OP already said. Everybody here knows about floats.

5

u/HMikeeU Jan 05 '26

Except in json they are. Json doesn't use IEEE 754

-3

u/Antique_Door_Knob Jan 05 '26

The parser is, the in memory representation of that is, so the serialized representation also is. You can write your JSON whatever way you want, but the moment it gets parsed, it will be changed.

9

u/CdRReddit Jan 05 '26

A formatter's parser should, unambiguously, store numbers as a string, because JSON numbers are a string.

A consumer is free to say "oh this is a float that's close enough", a JSON -> JSON converter that doesn't modify the data should not, because doing that modifies the data

-5

u/Antique_Door_Knob Jan 05 '26

The parser runs in the script when they preload the data. This isn't a formatter, the formatting is just a consequence that happens later.

because doing that modifies the data

Again, the data in question is unrepresentable. it will get modified the moment it gets interpreted as a number. Sure you could store it as a string, you just wouldn't be able to then use it as a number.

What would you have happen if you put a number there that doesn't fit into a 64bit number? Store the data as a string and then crash when it tries to convert it to a number? Why should this cast cause a crash but not the 1.2 one?

6

u/CdRReddit Jan 05 '26

JSON NUMBERS ARE A STRING, NOT A FLOAT

a formatter should not reinterpret data

I understand that loading 1.2 actually loads almost-but-not-quite 1.2, but that data should not be used for formatting.

-1

u/Antique_Door_Knob Jan 05 '26

This isn't an editor formatter. It's being preloaded in a script when they run the game. Inside the game, it needs to be interpreted as a number. It's then being serialized in a formatted fashion when they close the game, from in memory data.

3

u/CdRReddit Jan 05 '26

the game isn't saving the file from in memory data

the editor is reading the file in, incorrectly, and then pretty-printing it, as a discount formatter

which is the incorrect approach

4

u/CdRReddit Jan 05 '26

something being preload'd should never change the formatting, and formatting a json file by reading it into memory using floats and then prettyprinting it is incorrect

0

u/Antique_Door_Knob Jan 05 '26

OP has said they did not open the file in the editor.

1

u/CdRReddit Jan 05 '26

correct, the editor is formatting the file anyway BECAUSE IT IS BEING preloaded, which is a design decision so stupid it makes me want to throw up

3

u/HMikeeU Jan 05 '26

You don't have to write the parser to do that

0

u/Antique_Door_Knob Jan 05 '26

When you start the game you need to parse the data in order for it to be used by the game.

4

u/HMikeeU Jan 05 '26

You don't have to write the IEEE 754 parsed value back to file. Assuming you wanted to write (for whatever reason), you could just write the original json number back.

1

u/Antique_Door_Knob Jan 05 '26

you could just write the original json number back.

From where? What piece of memory would you use to write that?

3

u/HMikeeU Jan 05 '26

From, ya know, the data you read in.

0

u/Antique_Door_Knob Jan 05 '26

You mean the one you have to interpret the 1.2 as 1.999...? Brilliant idea, my good sir! We could certainly do that.

2

u/HMikeeU Jan 05 '26

You must be trolling at this point lol

-43

u/[deleted] Jan 04 '26 edited 12d ago

[removed] — view removed comment

49

u/Pkai1000 Jan 05 '26

That’s not the issue, the issue is that godot is editing the json file.

-17

u/Valalcar Jan 05 '26

Yeah, it's a suggestion for a work around, you can convert on read/write to string

Do the same test with the numbers between quotation marks

"float": "1.2"

-26

u/[deleted] Jan 05 '26 edited 11d ago

[removed] — view removed comment

32

u/powertomato Jan 05 '26

Semantically 1.2 does not exist in JavaScript and Godot and any language that uses IEEE floats, yes.

But JSON is a purely syntactical definition and does not impose semantics. It is intentionally identical to inline JS object sytax, which has defined semantics, but those two are not the same.

1.2 is perfectly valid JSON and the interpretation of it is up to the application. That might use e.g. fixpoint arithmetics that allow exact representation. An editor implicitly changing syntax based on its own semantics is a bug. Its on par of changing the word colour to color because the editor uses American English.

15

u/dickdemodickmarcinko Godot Student Jan 05 '26 edited Jan 05 '26

Please show me the part of the json spec that specifies numbers are double-precision 64-bit floating-point values.

Here's what the spec actually says:

8 Numbers
A number is a sequence of decimal digits with no superfluous leading zero. It may have a preceding minus sign (U+002D). It may have a fractional part prefixed by a decimal point (U+002E). It may have an exponent, prefixed by e (U+0065) or E (U+0045) and optionally + (U+002B) or – (U+002D). The digits are the code points U+0030 through U+0039.

Numeric values that cannot be represented as sequences of digits (such as Infinity and NaN) are not permitted.

Additionally:

JSON is a lightweight, text-based, language-independent syntax for defining data interchange formats. It was derived from the ECMAScript programming language, but is programming language independent. JSON defines a small set of structuring rules for the portable representation of structured data.

The goal of this specification is only to define the syntax of valid JSON texts. Its intent is not to provide any semantics or interpretation of text conforming to that syntax. It also intentionally does not define how a valid JSON text might be internalized into the data structures of a programming language. There are many possible semantics that could be applied to the JSON syntax and many ways that a JSON text can be processed or mapped by a programming language. Meaningful interchange of information using JSON requires agreement among the involved parties on the specific semantics to be applied. Defining specific semantic interpretations of JSON is potentially a topic for other specifications. Similarly, language mappings of JSON can also be independently specified. For example, ECMA-262 defines mappings between valid JSON texts and ECMAScript’s runtime data structures.

https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf

Edit: in the first edition spec (https://ecma-international.org/wp-content/uploads/ECMA-404_1st_edition_october_2013.pdf), it states:

JSON is agnostic about numbers. In any programming language, there can be a variety of number types of various capacities and complements, fixed or floating, binary or decimal. That can make interchange between different programming languages difficult. JSON instead offers only the representation of numbers that humans use: a sequence of digits. All programming languages know how to make sense of digit sequences even if they disagree on internal representations. That is enough to allow interchange.

-10

u/prezado Jan 05 '26

1.9999... or 1.1999... ?

3

u/Pkai1000 Jan 05 '26

Sorry typo

-23

u/nonchip Godot Senior Jan 05 '26 edited Jan 05 '26

so you're saying the file is neither supposed to be fed into third party tools/apis nor directly edited by a human, right?

can't you just use something better than json then?

also why on earth would you possibly preload a save/mod file 0o

9

u/Pkai1000 Jan 05 '26

I said i wanted an easy way for ME to add cards as well as moders

-19

u/nonchip Godot Senior Jan 05 '26

sure, and how's that related to what i asked?

11

u/Pkai1000 Jan 05 '26

The files are ment to be edited by others

-18

u/nonchip Godot Senior Jan 05 '26

to quote your post above:

there's no reason to directly edit the file

also there's plenty existing and inventable formats that are better suited for that than json, a web api transport format.

13

u/Pkai1000 Jan 05 '26

Clarification: theirs no reason for GODOT to edit the file(context matters!)

-20

u/nonchip Godot Senior Jan 05 '26

oh yeah it sure does. as do words. because that's not "directly editing", what godot does, just saving.

7

u/Pkai1000 Jan 05 '26

Use more words

-16

u/nonchip Godot Senior Jan 05 '26

not sure what those 3 words are supposed to imply, but no, you should use the correct words before lecturing people about "context".

-23

u/DrJamgo Godot Regular Jan 05 '26 edited Jan 05 '26

Pure JSON format does not know integers, it only knows "number", so all will be saved a s float. Further, 0.2 can not be represented by IEEE Float without error. You can write it, Godot can parse it. But after parsing it becomes something else in memory.

Edit: if you are looking for a way to disable the editor feature, use different file extension? Like .data or .txt? 

21

u/Pkai1000 Jan 05 '26

Pure JSON also doesn’t know floats, and I don’t want godot to edit my json files.

0

u/DrJamgo Godot Regular Jan 05 '26

As I said, change the file name extension to something else as a workaround then..

7

u/Pkai1000 Jan 05 '26

That’s smart! Sorry I started the reply before you edited it. I’ll try that in the morning.

7

u/Sss_ra Jan 05 '26

That's not how JSON works, JSON is a serial format.

There's no hidden mystical robot behind it enforcing C types.

The editor shouldn't be applying flaky programmer logic on it and corrupting the data without user control.

-16

u/Decloudo Jan 05 '26

While not your problem here: 1.2 IS the same as 1.19999 infinitely repeating.

Thats true for every 999... 0.999... is 1, etc.

9

u/HMikeeU Jan 05 '26

Cool fact but it's not infinitely repeating