Почему клавиши int питона python превращаются в строки при использовании json.dumps?
В соответствии с эта таблица преобразования, Python ints записывается как JSON-номера при сериализации с использованием модуля JSON - как я ожидал бы и желал бы.
У меня есть словарь с целым и целочисленным значениями:
>>> d = {1:2}
>>> type(d.items()[0][0])
<type 'int'>
>>> type(d.items()[0][1])
<type 'int'>
Когда я использую модуль json для сериализации этой строки в строке JSON, значение записывается как число, но ключ записывается как строка:
>>> json.dumps(d)
'{"1": 2}'
Это не то поведение, которое я хочу, и он кажется особенно сломанным, так как он прерывает json.dumps/json.loads round-trip:
>>> d == json.loads(json.dumps(d))
False
Почему это происходит, и есть ли способ заставить ключ быть записанным как число?
Ответы
Ответ 1
Простая причина в том, что JSON не разрешает целочисленные ключи.
object
{}
{ members }
members
pair
pair , members
pair
string : value # Keys *must* be strings.
Что касается того, как обойти это ограничение - сначала вам нужно убедиться, что принимающая реализация может обрабатывать технически недействительный JSON. Затем вы можете либо заменить все метки кавычек, либо использовать собственный сериализатор.
Ответ 2
Если вы действительно хотите, вы можете проверить ключи на возможность конвертации в целые числа снова, используя:
def pythonify(json_data):
for key, value in json_data.iteritems():
if isinstance(value, list):
value = [ pythonify(item) if isinstance(item, dict) else item for item in value ]
elif isinstance(value, dict):
value = pythonify(value)
try:
newkey = int(key)
del json_data[key]
key = newkey
except TypeError:
pass
json_data[key] = value
return json_data
Ответ 3
Эта функция будет рекурсивно приводить все строковые ключи к int-ключам, если это возможно. Если это невозможно, тип ключа останется неизменным.
Я немного поправил пример JLT ниже. В некоторых моих огромных вложенных словарях этот код изменял размер словаря, заканчиваясь исключением. Во всяком случае, кредит идет на JLT!
def pythonify(json_data):
correctedDict = {}
for key, value in json_data.items():
if isinstance(value, list):
value = [pythonify(item) if isinstance(item, dict) else item for item in value]
elif isinstance(value, dict):
value = pythonify(value)
try:
key = int(key)
except Exception as ex:
pass
correctedDict[key] = value
return correctedDict