Я пытаюсь создать строковое представление JSON экземпляра класса и испытываю трудности. Допустим, класс построен так:
class testclass:
value1 = "a"
value2 = "b"
Вызов в json.dumps делается так:
t = testclass()
json.dumps(t)
Это провал и говорит мне, что тестовый класс не JSON-сериализуемый.
TypeError: <__main__.testclass object at 0x000000000227A400> is not JSON serializable
Я также попытался использовать модуль рассола:
t = testclass()
print(pickle.dumps(t, pickle.HIGHEST_PROTOCOL))
И это дает информацию об экземпляре класса, но не сериализованное содержимое экземпляра класса.
b'\x80\x03c__main__\ntestclass\nq\x00)\x81q\x01}q\x02b.'
Что я делаю не так?
python
json
serialization
pickle
Ферхан
источник
источник
s = json.dumps(obj, default=lambda x: x.__dict__)
к переменным экземпляра сериализации объекта (self.value1
,self.value2
, ...). Это самый простой и прямой путь. Он будет сериализовать вложенные объектные структуры.default
Функция вызывается , когда какой - либо данный объект непосредственно не сериализации. Вы также можете посмотреть мой ответ ниже. Я нашел популярные ответы излишне сложными, которые, вероятно, были верны довольно давно.testclass
нет__init__()
метода, поэтому все экземпляры будут использовать одни и те же атрибуты класса (value1
иvalue2
), определенные в операторе класса. Вы понимаете разницу между классом и его экземпляром?Ответы:
Основная проблема заключается в том, что кодировщик JSON
json.dumps()
знает, как по умолчанию сериализовать ограниченный набор типов объектов, все встроенные типы. Список здесь: https://docs.python.org/3.3/library/json.html#encoders-and-decodersОдним хорошим решением было бы сделать так, чтобы ваш класс наследовал,
JSONEncoder
а затем реализовалJSONEncoder.default()
функцию, и чтобы эта функция генерировала правильный JSON для вашего класса.Простое решение было бы назвать
json.dumps()
на.__dict__
члене этого экземпляра. Это стандартный Python,dict
и если ваш класс прост, он будет сериализуем JSON.Вышеупомянутый подход обсужден в этой публикации блога:
Сериализация произвольных объектов Python в JSON с использованием __dict__
источник
.__init__()
функции-метода, поэтому у вашего экземпляра класса есть пустой словарь. Другими словами,{}
это правильный результат для вашего примера кода.is not JSON serializable
Есть один способ, который отлично работает для меня, который вы можете попробовать:
json.dumps()
может принимать необязательный параметр default, где вы можете указать настраиваемую функцию сериализатора для неизвестных типов, которая в моем случае выглядит следующим образомПервые два if предназначены для сериализации даты и времени, а затем есть
obj.__dict__
возврат для любого другого объекта.последний звонок выглядит так:
Это особенно хорошо, когда вы сериализуете коллекцию и не хотите
__dict__
явно вызывать каждый объект. Здесь это делается для вас автоматически.До сих пор работал так хорошо для меня, с нетерпением жду ваших мыслей.
источник
NameError: name 'serialize' is not defined
. Какие-нибудь советы?try: dict = obj.__dict__ except AttributeError: dict = {s: getattr(obj, s) for s in obj.__slots__ if hasattr(obj, s)} return dict
Вы можете указать
default
именованный параметр вjson.dumps()
функции:Объяснение:
Формируем документы ( 2.7 , 3.6 ):
(Работает на Python 2.7 и Python 3.x)
Примечание: в этом случае вам нужны
instance
переменные, а неclass
переменные, как пытается сделать пример в вопросе. (Я предполагаю, что спрашивающий долженclass instance
быть объектом класса)Я узнал об этом первым из ответа @ phihag здесь . Нашел, что это самый простой и чистый способ сделать работу.
источник
default=lambda x: getattr(x, '__dict__', str(x))
datetime.date
является реализацией C, следовательно, она не имеет__dict__
атрибута. ИМХО ради единообразия,datetime.date
должно быть это ...Я просто:
Это не полный ответ, и если у вас есть какой-то сложный объектный класс, вы, конечно, не получите все. Однако я использую это для некоторых из моих простых объектов.
Тот, на котором он действительно хорошо работает - это класс «options», который вы получаете из модуля OptionParser. Здесь это вместе с самим запросом JSON.
источник
Используя jsonpickle
источник
JSON не предназначен для сериализации произвольных объектов Python. Он отлично подходит для сериализации
dict
объектов, ноpickle
модуль действительно то, что вы должны использовать в целом. Вывод изpickle
не очень удобочитаемый, но он должен просто распечатать. Если вы настаиваете на использовании JSON, вы можете проверитьjsonpickle
модуль, который представляет собой интересный гибридный подход.https://github.com/jsonpickle/jsonpickle
источник
Вот две простые функции для сериализации любых несложных классов, ничего необычного, как объяснено ранее.
Я использую это для типа конфигурации, потому что я могу добавлять новые классы без корректировок кода.
источник
Есть несколько хороших ответов о том, как начать делать это. Но есть некоторые вещи, которые нужно иметь в виду:
__slots__
вместо__dict__
?json-tricks - это библиотека (которую я создал, и другие внесли свой вклад), которая смогла сделать это довольно давно. Например:
Вы получите свой экземпляр обратно. Здесь JSON выглядит так:
Если вы хотите сделать свое собственное решение, вы можете взглянуть на источник,
json-tricks
чтобы не забыть некоторые особые случаи (например__slots__
).Это также делает другие типы как массивы числа, datetime, комплексные числа; это также позволяет для комментариев.
источник
Python3.x
Наилучшим подходом, которого я мог достичь с помощью моих знаний, было это.
Обратите внимание, что этот код также обрабатывает set ().
Этот подход является общим, просто требуется расширение класса (во втором примере).
Обратите внимание, что я просто делаю это с файлами, но легко изменить поведение на свой вкус.
Однако это кодек.
Приложив немного больше работы, вы можете построить свой класс другими способами. Я предполагаю, что конструктор по умолчанию его создает, а затем обновляю класс dict.
редактировать
Проведя дополнительные исследования, я нашел способ обобщения без необходимости вызова метода регистра SUPERCLASS с использованием метакласса.
источник
Я считаю, что вместо наследования, как предлагается в принятом ответе, лучше использовать полиморфизм. В противном случае вы должны иметь большой оператор if else для настройки кодировки каждого объекта. Это означает, что создайте общий кодировщик по умолчанию для JSON как:
а затем есть
jsonEnc()
функция в каждом классе, который вы хотите сериализовать. напримерТогда вы звоните
json.dumps(classInstance,default=jsonDefEncoder)
источник