Why JSON formatting can change your data
Reproduce large-number rounding and duplicate-key loss, locate the stage that changed a payload, and choose a safer debugging workflow.
By Sujit Maharjan. Published .
Trace a changed value back to parsing, then preserve the evidence before reformatting.
Keep the original before investigating
An API returns a long order ID. You paste the response into a formatter, copy the result into a bug report, and the last digit is different. The document still parses. A second formatter may even agree with the changed value. What happened?
Formatting can involve two operations: parsing text into a language’s values, then serializing those values back to text. Information can disappear in the first operation. Changing indentation afterward cannot restore it. Start the investigation by keeping the exact original response separately from every generated version.
Use the synthetic parsing file for this exercise. It deliberately includes problematic values and duplicate keys. It contains no customer data. Save it before opening JSON Formatter; the downloaded output is a separate artifact, not a backup of the input.
Reproduce a round trip without the UI
Run the following JavaScript in a local Node.js session. The example is synthetic and does not need a network request.
const original = '{"id":9007199254740993,"status":"draft","status":"published"}';
const parsed = JSON.parse(original);
console.log(JSON.stringify(parsed));
// {"id":9007199254740992,"status":"published"}Two independent changes occurred. JavaScript’s numeric representation cannot distinguish every integer at this size, and parsing retained the last status value. The formatter did not invent these behaviors: it uses the same parse-and-serialize operations. A tool that preserves raw number tokens could behave differently.
Now change the ID to a string:
const original = '{"id":"9007199254740993","status":"published"}';
console.log(JSON.stringify(JSON.parse(original)));
// {"id":"9007199254740993","status":"published"}This preserves these exact digits because the ID is now text. It does not establish that the downstream API accepts a string. Check the contract before changing the type in a production integration.
Locate the stage that changed the value
Inspect the raw response, the value immediately after parsing, and the serialized output separately. If the raw response is already wrong, formatting is downstream of the problem. If the text is right but the parsed number is wrong, inspect the parser’s number model. If the parsed value is right but output differs, inspect serialization and transformations such as key sorting.
| Symptom | Next check | What agreement does not prove |
|---|---|---|
| Last digits of an ID changed | Compare the original numeric token with the parsed value | Two JavaScript-based tools can agree after the same rounding |
| An earlier duplicate field disappeared | Read the original text before parsing | An ordinary object cannot show both duplicate entries |
1e2 became 100 | Separate number spelling from numeric value | Changed spelling alone is not a changed numeric value |
A huge number became null | Check finite-range overflow and serialization | Valid output syntax does not mean the original number survived |
The downloadable file produces five keys after parsing. Its numericId becomes 9007199254740992, its stringId keeps the original digits, its last status is published, its amount becomes 100, and its overflowing number serializes as null. These are specific expected outputs of this implementation, not universal behavior for all JSON software.
Choose the comparison that answers your question
Use Text Diff Checker when the question is “Did the original bytes or spelling change?” Keep comparison normalization off when whitespace and case are evidence. This tool compares text lines; it is not a binary checksum.
Use JSON Diff Checker when the question is “Which parsed fields changed?” Its structural comparison ignores object-key order and formatting. Since it also uses JavaScript parsing, it cannot recover discarded duplicate keys or distinguish every large integer. A structural Identical result is therefore insufficient evidence for a lossless round trip.
A useful bug report includes the original synthetic input, the parser/runtime used, the generated output and the expected contract. Avoid a screenshot alone: someone should be able to copy the fixture and reproduce the result.
Prevent recurrence at the boundary
Decide whether a field represents an identifier or a quantity. An opaque identifier often needs exact characters rather than arithmetic; if the API permits strings, specify and test that representation end to end. If the API requires exact large numeric tokens, use tooling that supports the required precision and verify its serialization behavior.
Reject or explicitly handle duplicate names before information is lost when your workflow requires detecting them. Testing the already-parsed object cannot reveal a duplicate that the parser discarded. Preserve the raw payload when debugging signatures over serialized content as well: key order and whitespace can matter to a byte-level signature even when parsed data agrees.
Add a regression fixture at the boundary where the failure happened. Assert the exact expected ID or raw output, rather than generating the expected answer with the same parse operation under test. A green syntax indicator should never replace a schema or integration check.
Sources and scope
RFC 8259, sections 4 and 6 discusses object-name uniqueness and numeric interoperability. The JavaScript examples and downloadable outputs above describe UToolios’s current implementation and can be reproduced locally.
These examples were prepared with AI assistance and checked against the tool implementation and automated fixtures. They are illustrative, not a report of a customer incident. How UToolios content is maintained.