Я обнаружил, что при следующем запуске json-модуль python (включенный с версии 2.6) преобразует ключи словаря int в строки.
>>> import json
>>> releases = {1: "foo-v0.1"}
>>> json.dumps(releases)
'{"1": "foo-v0.1"}'
Есть ли простой способ сохранить ключ как int, без необходимости анализировать строку при дампе и загрузке. Я считаю, что можно было бы использовать хуки, предоставленные модулем json, но опять же, это все еще требует синтаксического анализа. Есть ли аргумент, который я упустил из виду? ура, Чаз
Подвопрос: Спасибо за ответы. Видя, как json работает так, как я опасался, есть ли простой способ передать тип ключа, возможно, проанализировав вывод дампа? Также я должен отметить, что код, выполняющий дамп, и код, загружающий объект json с сервера и загружающий его, написаны мной.
Ответы:
Это одно из тех тонких различий между различными коллекциями карт, которые могут вас укусить. JSON обрабатывает ключи как строки; Python поддерживает отдельные ключи, различающиеся только типом.
В Python (и, очевидно, в Lua) ключи к отображению (словарь или таблица, соответственно) являются ссылками на объекты. В Python они должны быть неизменяемыми типами или должны быть объектами, реализующими
__hash__
метод. (Документы Lua предполагают, что он автоматически использует идентификатор объекта в качестве хэша / ключа даже для изменяемых объектов и полагается на интернирование строк, чтобы гарантировать, что эквивалентные строки сопоставляются с одними и теми же объектами).В Perl, Javascript, awk и многих других языках ключи для хэшей, ассоциативных массивов или того, что они называются для данного языка, являются строками (или «скалярами» в Perl). В Perl
$foo{1}, $foo{1.0}, and $foo{"1"}
все ссылки на одно и то же отображение%foo
--- ключ оценивается как скаляр!JSON начинался как технология сериализации Javascript. (JSON означает J AVA S cript O ▪ Таблица N otation.) Естественно , что она реализует семантику для его отображения обозначений , которые согласуются с его отображения семантики.
Если оба конца вашей сериализации будут Python, вам лучше использовать соленья. Если вам действительно нужно преобразовать их обратно из JSON в собственные объекты Python, я думаю, у вас есть несколько вариантов. Сначала вы можете попробовать (
try: ... except: ...
) преобразовать любой ключ в число в случае сбоя поиска по словарю. В качестве альтернативы, если вы добавите код на другой конец (сериализатор или генератор этих данных JSON), вы можете заставить его выполнить сериализацию JSON для каждого из значений ключа, предоставив их в виде списка ключей. (Тогда ваш код Python сначала будет перебирать список ключей, создавая / десериализуя их в собственные объекты Python ... а затем использовать их для доступа к значениям из сопоставления).источник
Нет, в JavaScript нет такой вещи, как цифровая клавиша. Все свойства объекта преобразуются в String.
Это может привести к появлению странного поведения:
Объекты JavaScript на самом деле не совсем правильные сопоставления, как вы понимаете на таких языках, как Python, а использование ключей, которые не являются String, приводит к странностям. Вот почему JSON всегда явно записывает ключи в виде строк, даже если это не кажется необходимым.
источник
999999999999999999999
конвертируется в'999999999999999999999'
?Number
Тип представляет собой двойной IEEE 754 значение с плавающей запятой: вы получаете 53 бит мантиссы, так что вы можете хранить до 2⁵³ (9007199254740992) с целочисленной точностью; помимо этого целые числа будут округляться до других значений (следовательно, 9007199254740993 === 9007199254740992). 999999999999999999999 округляется до 1000000000000000000000, для которого используетсяtoString
представление по умолчанию1e+21
.В качестве альтернативы вы также можете попробовать преобразовать словарь в список формата [(k1, v1), (k2, v2)] при его кодировании с помощью json и преобразовать обратно в словарь после его обратного декодирования.
Я считаю, что для этого потребуется дополнительная работа, например, наличие какого-то флага, чтобы определить, какие все параметры будут преобразованы в словарь после его декодирования из json.источник
Отвечая на ваш вопрос:
Это можно сделать, используя
json.loads(jsonDict, object_hook=jsonKeys2int)
Эта функция также будет работать для вложенных dicts и использует понимание dict.
Если вы хотите также использовать значения, используйте:
Что проверяет экземпляр значений и отбрасывает их только в том случае, если они являются строковыми объектами (точнее, Unicode).
Обе функции предполагают, что ключи (и значения) являются целыми числами.
Благодаря:
Как использовать if / else в понимании словаря?
Преобразование строкового ключа в int в словаре
источник
Меня укусила та же проблема. Как указывали другие, в JSON ключи сопоставления должны быть строками. Вы можете сделать одно из двух. Вы можете использовать менее строгую библиотеку JSON, например demjson , которая позволяет использовать целочисленные строки. Если никакие другие программы (или никакие другие программы на других языках) не собираются его читать, значит, все в порядке. Или вы можете использовать другой язык сериализации. Я бы не советовал рассол. Его трудно читать, и он не предназначен для обеспечения безопасности . Вместо этого я бы предложил YAML, который (почти) является расширенным набором JSON и допускает целочисленные ключи. (По крайней мере, PyYAML .)
источник
Преобразуйте словарь в строку с помощью,
str(dict)
а затем преобразуйте его обратно в dict, выполнив следующие действия:источник
Вот мое решение! Я использовал
object_hook
, это полезно, когда вы вложилиjson
Есть фильтр только для разбора json-ключа на int. Вы также можете использовать
int(v) if v.lstrip('-').isdigit() else v
фильтр для значения json.источник
Я сделал очень простое расширение ответа Мурмеля, которое, как я думаю, будет работать с довольно произвольным словарем (включая вложенный), предполагая, что он может быть сброшен JSON в первую очередь. Любые ключи, которые можно интерпретировать как целые числа, будут преобразованы в int. Без сомнения, это не очень эффективно, но это работает для моих целей хранения и загрузки из строк json.
Предполагая, что все ключи в исходном dict являются целыми числами, если они могут быть преобразованы в int, тогда это вернет исходный словарь после сохранения как json. например
источник
Вы можете написать свое
json.dumps
самостоятельно, вот пример из djson : encoder.py . Вы можете использовать это так:источник