#python #json #deserialization
#python #json #десериализация
Вопрос:
Я работаю со службой обмена сообщениями, используя API на основе python. API выполняет большую часть работы по десериализации, переводя сообщения в словари python. Однако в некоторых случаях отображаемый словарь включает пару ключ / значение метаданных, где значение представляет собой строковый рендеринг словаря, который не был десериализован. Я создал простой метод десериализации, но мне пришлось неоднократно вносить в него изменения, чтобы охватить три различия между python и JSON, то есть одинарные и двойные кавычки, различия в регистре логических значений и None и null:
def deserializeMetaData(metaDataStr):
metaDataStr = metaDataStr.replace("'",'"').replace('True', 'true').replace('False', 'false').replace('None', 'null')
metaDataDict = json.loads(metaDataStr)
return metaDataDict
metaDataStr = "{'SomeCount': 1, 'SomeOtherCount': 2, 'SomeBool': True, 'SomethingElse': None}"
deserializeMetaData(metaDataStr)
{'SomeCount': 1, 'SomeOtherCount': 2, 'SomeBool': True, 'SomethingElse': None}
Похоже, действительно плохая практика нацеливаться на конкретные угловые случаи, как у меня с повторным вызовом replace
. Есть ли другой способ подойти к этому, который бы лучше охватывал эти и все угловые случаи?
Комментарии:
1. Почему бы вам просто не использовать действительный сериализатор?
2. @ScottHunter можете ли вы подробнее рассказать об этом? Не уверен, каким будет допустимый десериализатор.
3. Тот, который выдает допустимый JSON; например
json.dumps
.
Ответ №1:
Возможно metaDataStr
, неправильно интерпретировался как JSON, который необходимо десериализовать. Вместо этого просмотр его как строкового литерала словаря приводит к модулю абстрактного синтаксического дерева (ast).
Безопасно вычислите узел выражения или строку, содержащую литерал Python или отображение контейнера. Предоставленная строка или узел могут состоять только из следующих литеральных структур Python: строк, байтов, чисел, кортежей, списков, dicts, наборов, логических значений и None.
Это можно использовать для безопасной оценки строк, содержащих значения Python из ненадежных источников, без необходимости самостоятельного анализа значений. Он не способен вычислять произвольно сложные выражения, например, с использованием операторов или индексации.
Итак, следующего достаточно, чтобы преобразовать строку в словарь без проблем:
import ast
metaDataStr = "{'SomeCount': 1, 'SomeOtherCount': 2, 'SomeBool': True, 'SomethingElse': None}"
d = ast.literal_eval(metaDataStr)
type(d)
Out[18]: dict