Klemm’s sample CSV has a customer ID called 0007.
Turn it into an integer and Python happily gives you 7. Put that in JSON and the parser is happy too. If the next system expects the original identifier, you have changed the data without breaking the file.
The boring-looking zeros were doing a job.
A format conversion is also a policy decision
Klemm published a small CSV-to-JSON converter. I downloaded its source ZIP and ran these two fictional records locally:
customer_id,postcode,active,balance
0007,00120,false,12.00
0042,01001,true,0.00
The command wrote two records. The first object in the resulting JSON array was:
{
"customer_id": "0007",
"postcode": "00120",
"active": "false",
"balance": "12.00"
}
Every value is a string. That is a deliberate rule in this converter, rather than a guess about the destination’s schema.
An identifier can contain digits without being a quantity. And the column name active does not, by itself, tell a CSV reader which spellings the receiving API accepts as booleans.
“Helpful” has three different meanings here
I also checked these ordinary Python conversions:
int("0007") # 7
float("12.00") # 12.0
bool("false") # True
The first loses the identifier’s formatting. The second changes decimal formatting while retaining the same numeric value in this example. The third is a different trap: a non-empty string is truthy. Python is not reading the word “false” as a boolean instruction.
None of those results is a JSON syntax error. Whether each is acceptable depends on the field’s contract.
Put the decision next to the field
If the destination requires an actual boolean, make that mapping explicit:
accepted_flags = {"true": True, "false": False}
active = accepted_flags[row["active"]]
This tiny adapter accepts exactly those two lowercase spellings; an unexpected value raises KeyError. A real import should turn that into a useful validation message, or deliberately define additional accepted spellings. It should not quietly treat every non-empty cell as true.
Keep the customer ID as text when the receiving contract requires its zeros. Decide the other fields separately.
The converter also rejects malformed headers and wrong-width rows, and protects existing output unless overwrite is explicitly selected. It handles small UTF-8 files in memory; it does not supply a business schema for you. My run above checks the two fictional records, not somebody’s production import.
Source, runnable examples and documented checks.
Related: when Python equality is not your JSON contract.
A parser can tell you that the brackets match. It cannot decide what 0007 means to the next system.
Top comments (0)