JSON numbers and duplicate keys: preserve the original digits and names
Check large integers, decimal precision, duplicate names, member order, and CSV leading zeros against real tool behavior.
Keep the original JSON text until you know how the receiving parser treats numbers and repeated names. A green validation result establishes syntax, not preservation of every digit or member. Pretty output can hide a destructive parse-and-serialize step. Our formatter avoids that step, but other operations on the same site have different limits.
Treat identifiers as strings when their digits identify records rather than quantities. For monetary decimals, agree on a decimal representation and arithmetic policy before exchanging JSON. Reject duplicate names before choosing one value for an object member. Those decisions matter more than indentation or alphabetical key order.
Strict JSON syntax
JSON Formatter and JSON Validator reject comments, trailing commas, single quotes, unquoted names, and NaN. They also reject a leading byte order mark. Remove that mark before pasting the document.RFC 8259 defines the JSON grammar.
Choose the operation by what it preserves
| Tool | What it does | What its result cannot prove |
|---|---|---|
| JSON Formatter | Changes whitespace around original tokens. Keeps numeric spelling, duplicate names, and member order. | Preserved duplicate names can still cause disagreements between downstream parsers. |
| JSON Comparator | Compares exact decimal values. Rejects duplicate names and ignores object member order. Accepts trailing commas. | Equal values need not have identical text, numeric spelling, or signature bytes. Equality does not prove valid JSON syntax. |
| JSON Validator | Checks accepted JSON or JSON Lines syntax. Accepts repeated object names. | Valid syntax does not promise unique names, an application schema, or safe numeric conversion. |
| CSV and JSON Converter | CSV input produces string cells. JSON input passes through JavaScript value parsing. Dictionary output reorders integer-like headers. | JSON-to-CSV can lose numeric precision, repeated names, and original member order. |
The comparator accepts {"a":1,} as equal to {"a":1}. Its parser also treats blank text as an empty object. Use the validator to check strict JSON syntax before comparing values.
ECMA-404, sections 1, 6, and 8 defines JSON syntax without prescribing language data structures. It does not require unique object names or assign meaning to member order. Applications must agree on stronger data rules when their records need them.
An integer can survive formatting and fail during conversion
ECMAScript's Number.MAX_SAFE_INTEGER equals 9007199254740991, or 2^53 - 1. The next integer, 9007199254740992, remains exactly representable. However, 9007199254740993 rounds to that same Number value. Beyond the safe boundary, distinct integer identifiers can therefore become indistinguishable.
Paste {"id":9007199254740993} into the JSON formatter with two-space indentation. It returns the following text, preserving the final digit:
{
"id": 9007199254740993
}Now compare {"id":9007199254740992} with {"id":9007199254740993} in the JSON comparator. Select Text output. The comparator reports:
id: Mismatch: 9007199254740992 != 9007199254740993The formatter keeps source number tokens; the comparator compares their decimal values without Number rounding. Neither result guarantees that a database driver or another JSON consumer preserves those digits. Keep long record identifiers quoted throughout the pipeline. Converting an already rounded Number into a string cannot recover its original digits.
Preserve decimal value and decimal spelling separately
Binary floating-point cannot represent every finite decimal exactly. JavaScript evaluates 0.1 + 0.2 as 0.30000000000000004. JSON does not itself perform that arithmetic. RFC 8259, section 6 permits parser limits on numeric range and precision.
Format {"amount":1.2300,"precise":0.10000000000000001} to preserve both the trailing zeros and the longer decimal:
{
"amount": 1.2300,
"precise": 0.10000000000000001
}The comparator distinguishes {"n":0.1} from {"n":0.10000000000000001}:
n: Mismatch: 0.1 != 0.10000000000000001It treats {"n":[1.2300,1e2,-0]} and {"n":[1.23,100,0]} as equal, returning No differences found. This comparison checks numeric value, not significant figures, signed zero, or the sender's chosen exponent notation. Store an explicit scale when the number of decimal places carries meaning. Use agreed decimal arithmetic for amounts; adding zeros to displayed output does not repair rounded arithmetic.
Validation does not settle duplicate names
Paste {"role":"reader","role":"admin"} into the JSON validator. It reports valid: true and format: json. The formatter also accepts this input and keeps both members:
{
"role": "reader",
"role": "admin"
}RFC 8259, section 4 recommends unique names because duplicate handling varies between implementations. Some consumers retain the final value; others reject the object or expose multiple values. An access decision cannot safely depend on every consumer choosing the same occurrence.
Compare that object against {"role":"admin"}. Our comparator rejects the first input with Duplicate key "role" at line 1, column 18. Resolve the duplicate in the original source before comparing values. Choosing the final member merely because JavaScript keeps it turns an ambiguous record into an undocumented policy.
Duplicate detection must compare decoded member names within each object. Escape spelling does not create a different name when both strings decode to the same characters. Reusing a name in two separate nested objects does not create a duplicate within either object. A text search for repeated quotation marks cannot enforce this rule.
Object equality does not preserve serialization order
Compare {"a":1,"b":2} with {"b":2,"a":1}. The comparator returns No differences found because both objects map the same names to the same values. Compare arrays [1,2] and [2,1] instead:
0: Mismatch: 1 != 2
1: Mismatch: 2 != 1Array positions carry meaning in this comparison. Object member order does not provide a portable instruction sequence. Use an array when processing order belongs to the data contract. Keep original bytes when verifying a signature over serialized JSON; equivalent objects can have different signed bytes.
Format {"10":"ten","2":"two","a":"letter"}. The formatter keeps 10 before 2:
{
"10": "ten",
"2": "two",
"a": "letter"
}Send [{"10":"ten","2":"two","a":"letter"}] through JSON-to-CSV instead. JavaScript object enumeration places these integer-like property names first in numeric order. The resulting header becomes 2,10,a:
2,10,a
two,ten,letter
CSV to JSON also changes this order when you choose Array of dictionaries. Input 10,2,a followed by ten,two,letter produces members in the order 2,10,a. A later CSV export keeps that changed order. Choose Array of arrays when column positions must remain intact.
Keep leading zeros through the CSV boundary
In the CSV and JSON converter, select CSV to JSON. Keep comma cell delimiters and the default row delimiters. Choose Array of dictionaries, then enter:
code,count
00123,7The result keeps both cells as strings:
[
{
"code": "00123",
"count": "7"
}
]This CSV mode preserves 00123; it does not infer a numeric type for 7. The mode switch clears the input, so copy this JSON first. Paste it into JSON to CSV to reproduce this example's header and cell text, with CRLF row endings. A spreadsheet can still remove zeros when it later imports that CSV column as numeric data. Configure that column as text before import.
JSON syntax forbids an unquoted number such as 00123. The validator rejects {"code":00123} with a leading-zero error. Quote the identifier at the producer; do not remove its zeros to make validation pass.
JSON-to-CSV uses a different path. Enter [{"id":9007199254740993,"amount":0.10000000000000001}] and it returns:
id,amount
9007199254740992,0.1
Both numeric values lose source digits during JavaScript parsing. Enter [{"id":"9007199254740993","amount":"0.10000000000000001"}] to retain those exact decimal strings:
id,amount
9007199254740993,0.10000000000000001
Repeated names also collapse on this path. Input [{"role":"reader","role":"admin"}] produces a single role column containing admin. Compare and resolve duplicates before exporting records to CSV.
Common mistakes at the JSON boundary
- Do not equate valid JSON with lossless conversion. Check each operation's numeric and duplicate-name behavior.
- Do not compare already rounded identifiers. Preserve the original text before either input enters a Number-based parser.
- Do not use comparator equality as a byte comparison. It normalizes equivalent numbers and ignores object member order.
- Do not assume CSV quotes enforce a column type. The next importer controls numeric inference and leading-zero loss.