New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
json dump silently converts int keys to string #79153
Comments
When int keys are silently converted to string on json serialization, the user needs to remember to convert it back to int on loading. In my case I serialize a dict to json with int keys, later load it back into a dict (resulting in a dict with string keys) and test for existence of an int key in the dict which will then return False incorrectly. I am aware that json does not support int keys, but this can be easily forgotten. |
Thanks for the report. There was a related issue few days back bpo-32816. I think this is a documented behavior at https://docs.python.org/3.8/library/json.html#json.dumps . Having a warning in place might break code and I don't know if there is a safe way to introduce this as a code level warning given that this is a documented behavior in Python 2 and 3. I think this is the case with other languages too like JavaScript itself converting int to string without warning adhering to JSON standard. Correct me if I am wrong or other languages have a warning related to this
You can try doing json.loads(data, parse_int=int) but it will try converting the values. >>> json.loads(json.dumps({1:'1'}), parse_int=int)
{'1': '1'}
>>> json.loads(json.dumps({1:1}), parse_int=int)
{'1': 1} Thanks |
I don’t think, “other languages do that too” is a good argument here. This would apply if behaving differently would break user expectation. But here we would do nothing more than explicitly inform the user of a relevant operation. If they already expected that behaviour, they can disregard the warning. I don’t see how I would suggest a warning similar to this: --- json/encoder.py
+++ json/encoder.py
@@ -1,6 +1,7 @@
"""Implementation of JSONEncoder
"""
import re
+import warnings
try:
from _json import encode_basestring_ascii as c_encode_basestring_ascii
@@ -353,7 +354,9 @@
items = sorted(dct.items(), key=lambda kv: kv[0])
else:
items = dct.items()
+ non_str_key = False
for key, value in items:
+ non_str_key = non_str_key or not isinstance(key, str)
if isinstance(key, str):
pass
# JavaScript is weakly typed for these, so it makes sense to
@@ -403,6 +406,8 @@
else:
chunks = _iterencode(value, _current_indent_level)
yield from chunks
+ if non_str_key:
+ warnings.warn("Encountered non-string key(s), converted to string.", RuntimeWarning)
if newline_indent is not None:
_current_indent_level -= 1
yield '\n' + _indent * _current_indent_level |
I can't think of another place where we issue a warning for anything similar. I'm opposed to any changes here: it's clearly documented behavior. It's like being surprised .ini files convert to strings: it's just how that format works. |
Agreed with Eric. json.dump needs to produce valid JSON, which requires keys to be strings. Try using pickle if you need to preserve full Python semantics. |
Sure, I can do that, but wanted to propose this regardless. I guess this is a disagreement on a language design level. |
I understand (and agree with) the merits of automatically converting the int to str when dumping to a string. However, this result really surprised me: >>> json.dumps({1:2, "1":3})
'{"1": 2, "1": 3}' Is it a valid JSON? |
Similarly, keys can be lost entirely: >>> json.dumps({1:2, 1.0:3})
'{"1": 3}' |
(sorry, my example is normal Python behavior. {1:1, 1.0:2} == {1:2} , {1.0:1} == {1:1} ) |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: