ParseInt () и + разные
parseInt("10.3456") // returns 10
+"10.3456" // returns 10.3456
Я использовал эту стратегию в прошлом и был вполне доволен ею: Кодируйте ваши пользовательские объекты как объектные литералы JSON (как Python dict
s) со следующей структурой:
{ '__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}
}
}
}
Как указано в документации 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)