In my code, I have a nested dictionary and I want to ensure that key id
is an integer (note: it is a primary key). I tried just casting it to an int
but I am unsure if the key is an int
given that in the JSON there are double quotes.
See below my code and example of the data format.
statistics = defaultdict(dict)
\\in a loop
statistics[state][date].append({
int(id): {
"count_targets": targets,
"count_targets_excluded": excluded,
"count_targets_pending": pending,
"count_targets_in_progress": progress,
"count_targets_completed": completed,
"count_targets_failed": failed
}
})
{
"stateA": {
"2015-02-15": [
{
"13": {
"count_targets": 5,
"count_targets_excluded": 3,
"count_targets_pending": 3,
"count_targets_in_progress": 0,
"count_targets_completed": 1,
"count_targets_failed": 0
}
},
{
"14": {
"count_targets": 4,
"count_targets_excluded": 3,
"count_targets_pending": 3,
"count_targets_in_progress": 0,
"count_targets_completed": 1,
"count_targets_failed": 0
}
},
CodePudding user response:
JSON objects can only use JSON strings as keys:
>>> json.dumps({3: 4})
'{"3": 4}'
While the key in you dict
is certainly an int
, it gets converted to a string when encoding as JSON. JSON itself doesn't have a way of "remembering" the original type of the value used as a key, so you need some method (extra data in your JSON object, a pre-defined schema, etc) that the consumer of the JSON can use to turn the key back into an int
after decoding.
CodePudding user response:
JSON can not have ints as keys thus your ints get cast as string as soon as you convert your dictionary to JSON.
CodePudding user response:
in the JSON there are double quotes.
You have what is called Object in JSON parlance, RFC7159 situplates that
An object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a string.(...)
therefore, it will always have said quotes independently from type of key in python
dict, consider that
import json
original = {1:100}
serialized = json.dumps(original)
deserialized = json.loads(serialized)
print(serialized)
print(original==deserialized)
gives output
{"1": 100}
False
CodePudding user response:
You can't produce legal JSON that has int
keys, but if your goal is to parse incoming JSON with string keys that happen to represent valid int
s (which you may or may not have generated in Python), and have them become true int
s rather than str
, you can do this:
def maybe_int(key):
'''Converts strings that represent valid ints to int, leaving other strings unchanged'''
try:
return int(key)
except ValueError:
return key
def key_to_int(obj):
'''Replaces all string keys representing valid ints with ints'''
return {maybe_int(k): v for k, v in obj.items()}
myjsonstr = '{"1": 2}'
result = json.loads(myjsonstr, object_hook=key_to_int)
The hook is passed every decoded dict
(aka JSON object), and that decoded dict
is replaced by whatever the hook returns, in this case, a copy of the dict
where any key that int
can parse is replaced with its int
value.