Самый легкий способ сериализировать простой объект класса с simplejson?

ParseInt () и + разные

parseInt("10.3456") // returns 10

+"10.3456" // returns 10.3456
28
задан 26 February 2010 в 07:46
поделиться

2 ответа

Я использовал эту стратегию в прошлом и был вполне доволен ею: Кодируйте ваши пользовательские объекты как объектные литералы JSON (как Python dicts) со следующей структурой:

{ '__ClassName__': { ... } }

Это, по сути, один элемент dict, единственный ключ которого - специальная строка, определяющая тип объекта, а значение - dict атрибутов экземпляра. Если это имеет смысл.

Очень простая реализация кодера и декодера (упрощенная на основе кода, который я действительно использовал) выглядит так:

TYPES = { 'ParentClass': ParentClass,
          'ChildClass': ChildClass }


class CustomTypeEncoder(json.JSONEncoder):
    """A custom JSONEncoder class that knows how to encode core custom
    objects.

    Custom objects are encoded as JSON object literals (ie, dicts) with
    one key, '__TypeName__' where 'TypeName' is the actual name of the
    type to which the object belongs.  That single key maps to another
    object literal which is just the __dict__ of the object encoded."""

    def default(self, obj):
        if isinstance(obj, TYPES.values()):
            key = '__%s__' % obj.__class__.__name__
            return { key: obj.__dict__ }
        return json.JSONEncoder.default(self, obj)


def CustomTypeDecoder(dct):
    if len(dct) == 1:
        type_name, value = dct.items()[0]
        type_name = type_name.strip('_')
        if type_name in TYPES:
            return TYPES[type_name].from_dict(value)
    return dct

В этой реализации предполагается, что объекты, которые вы кодируете, будут иметь метод класса from_dict(), который знает, как воссоздать экземпляр из dict, декодированного из JSON.

Легко расширить кодировщик и декодировщик для поддержки пользовательских типов (например, datetime объектов).

EDIT, чтобы ответить на вашу правку: Самое приятное в такой реализации то, что она автоматически кодирует и декодирует экземпляры любого объекта, найденного в связке TYPES. Это означает, что он автоматически обработает ChildClass следующим образом:

class ChildClass(object):
    def __init__(self):
        self.foo = 'foo'
        self.bar = 1.1
        self.parent = ParentClass(1)

В результате в JSON должно получиться что-то вроде следующего:

{ '__ChildClass__': {
    'bar': 1.1,
    'foo': 'foo',
    'parent': {
        '__ParentClass__': {
            'foo': 1}
        }
    }
}
27
ответ дан 28 November 2019 в 03:30
поделиться

Как указано в документации JSON для Python // help(json.dumps) //>

Вам нужно просто переопределить метод default() для JSONEncoder, чтобы обеспечить пользовательское преобразование типов, и передать его как cls аргумент.

Вот один, который я использую, чтобы охватить специальные типы данных Монго (datetime и ObjectId)

class MongoEncoder(json.JSONEncoder):
    def default(self, v):
        types = {
            'ObjectId': lambda v: str(v),
            'datetime': lambda v: v.isoformat()
        }
        vtype = type(v).__name__
        if vtype in types:
            return types[type(v).__name__](v)
        else:
            return json.JSONEncoder.default(self, v)     

Называя его так же просто, как

data = json.dumps(data, cls=MongoEncoder)
2
ответ дан Tzury Bar Yochay 20 November 2019 в 03:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: