Подтвердить что ты не робот

Почему клавиши 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

Почему это происходит, и есть ли способ заставить ключ быть записанным как число?

4b9b3361

Ответ 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