Каков наилучший способ справиться с различиями между JSON и Python при десериализации?

#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