Как сделать класс JSON сериализуемым - PullRequest
650 голосов
/ 22 сентября 2010

Как сделать сериализуемый класс Python?

Простой класс:

class FileItem:
    def __init__(self, fname):
        self.fname = fname

Что я должен сделать, чтобы получить вывод:

json.dumps()

без ошибок (FileItem instance at ... is not JSON serializable)

Ответы [ 25 ]

0 голосов
/ 18 декабря 2018

Если вы можете установить пакет, я бы порекомендовал попробовать dill , который отлично работал для моего проекта. Приятной особенностью этого пакета является то, что он имеет тот же интерфейс, что и pickle, поэтому, если вы уже использовали pickle в своем проекте, вы можете просто заменить его в dill и посмотреть, работает ли сценарий, не изменяя код , Так что это очень дешевое решение!

(полное раскрытие информации: я никоим образом не связан и не участвовал в проекте укропа.)

Установить пакет:

pip install dill

Затем отредактируйте код для импорта dill вместо pickle:

# import pickle
import dill as pickle

Запустите ваш скрипт и посмотрите, работает ли он. (Если это так, вы можете очистить свой код, чтобы больше не скрывать имя модуля pickle!)

Некоторые особенности типов данных, которые dill могут и не могут сериализовать, начиная с страницы проекта :

dill можно мариновать следующие стандартные типы:

нет, тип, bool, int, long, float, complex, str, unicode, tuple, список, dict, файл, буфер, встроенный, старый и новый классы стилей, экземпляры старых и новых классов стилей, set, frozenset, array, функции, исключения

dill также можно мариновать более «экзотические» стандартные типы:

функции с выходами, вложенные функции, лямбда-выражения, ячейка, метод, unboundmethod, модуль, код, methodwrapper, dictproxy, methoddescriptor, getsetdescriptor, memberdescriptor, дескриптор оболочки, xrange, ломтик, не реализован, многоточие, выход

dill пока не может мариновать следующие стандартные типы:

рама, генератор, трассировка

0 голосов
/ 11 ноября 2017

Мне больше всего понравился метод Lost Koder.Я столкнулся с проблемами при попытке сериализовать более сложные объекты, члены / методы которых не сериализуемы.Вот моя реализация, которая работает на большем количестве объектов:

class Serializer(object):
    @staticmethod
    def serialize(obj):
        def check(o):
            for k, v in o.__dict__.items():
                try:
                    _ = json.dumps(v)
                    o.__dict__[k] = v
                except TypeError:
                    o.__dict__[k] = str(v)
            return o
        return json.dumps(check(obj).__dict__, indent=2)
0 голосов
/ 16 июля 2017

Я решил использовать декораторы для решения проблемы сериализации объекта datetime.Вот мой код:

#myjson.py
#Author: jmooremcc 7/16/2017

import json
from datetime import datetime, date, time, timedelta
"""
This module uses decorators to serialize date objects using json
The filename is myjson.py
In another module you simply add the following import statement:
    from myjson import json

json.dumps and json.dump will then correctly serialize datetime and date 
objects
"""

def json_serial(obj):
    """JSON serializer for objects not serializable by default json code"""

    if isinstance(obj, (datetime, date)):
        serial = str(obj)
        return serial
    raise TypeError ("Type %s not serializable" % type(obj))


def FixDumps(fn):
    def hook(obj):
        return fn(obj, default=json_serial)

    return hook

def FixDump(fn):
    def hook(obj, fp):
        return fn(obj,fp, default=json_serial)

    return hook


json.dumps=FixDumps(json.dumps)
json.dump=FixDump(json.dump)


if __name__=="__main__":
    today=datetime.now()
    data={'atime':today, 'greet':'Hello'}
    str=json.dumps(data)
    print str

Импортируя вышеупомянутый модуль, мои другие модули используют json обычным образом (без указания ключевого слова по умолчанию) для сериализации данных, которые содержат объекты даты и времени.Код сериализатора даты и времени автоматически вызывается для json.dumps и json.dump.

0 голосов
/ 21 мая 2015

Я придумал собственное решение.Используйте этот метод, передайте любой документ ( dict , список , ObjectId и т. Д.) Для сериализации.

def getSerializable(doc):
    # check if it's a list
    if isinstance(doc, list):
        for i, val in enumerate(doc):
            doc[i] = getSerializable(doc[i])
        return doc

    # check if it's a dict
    if isinstance(doc, dict):
        for key in doc.keys():
            doc[key] = getSerializable(doc[key])
        return doc

    # Process ObjectId
    if isinstance(doc, ObjectId):
        doc = str(doc)
        return doc

    # Use any other custom serializting stuff here...

    # For the rest of stuff
    return doc
0 голосов
/ 02 октября 2016

Есть много подходов к этой проблеме. ObjDict (pip install objdict) - это другое. Особое внимание уделяется предоставлению javascript-подобных объектов, которые также могут действовать как словари для лучшей обработки данных, загружаемых из JSON, но есть и другие функции, которые также могут быть полезны. Это обеспечивает другое альтернативное решение исходной проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...