使用simplejson序列化简单类对象的最简单方法?

28 python json simplejson

我正在尝试使用JSON(使用simplejson)序列化python对象列表,并且得到对象"不是JSON可序列化"的错误.

该类是一个简单的类,其字段只有整数,字符串和浮点数,并且从一个父超类继承类似的字段,例如:

class ParentClass:
  def __init__(self, foo):
     self.foo = foo

class ChildClass(ParentClass):
  def __init__(self, foo, bar):
     ParentClass.__init__(self, foo)
     self.bar = bar

bar1 = ChildClass(my_foo, my_bar)
bar2 = ChildClass(my_foo, my_bar)
my_list_of_objects = [bar1, bar2]
simplejson.dump(my_list_of_objects, my_filename)
Run Code Online (Sandbox Code Playgroud)

其中foo,bar是我上面提到的简单类型.唯一棘手的问题是ChildClass有时会有一个字段引用另一个对象(不是ParentClass或ChildClass的类型).

使用simplejson将此序列化为json对象的最简单方法是什么?将其序列化为字典是否足够?简单地为ChildClass 编写一个dict方法是最好的方法吗?最后,引用另一个对象的字段是否会使事情变得复杂化?如果是这样,我可以重写我的代码只在类中有简单的字段(如字符串/浮点数等)

谢谢.

Wil*_*hen 27

我用这个策略在过去,已经与它很高兴:编码为JSON对象文本您的自定义对象(如Python dict用以下结构S):

{ '__ClassName__': { ... } }
Run Code Online (Sandbox Code Playgroud)

这本质上是一个单项,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
Run Code Online (Sandbox Code Playgroud)

在此实现中,假设您正在编码的对象将具有一个from_dict()类方法,该方法知道如何dict从JSON解码中重新创建实例.

扩展编码器和解码器以支持自定义类型(例如datetime对象)很容易.

编辑,回答您的编辑:像这样的实现的好处是它将自动编码和解码TYPES映射中找到的任何对象的实例.这意味着它将自动处理ChildClass,如下所示:

class ChildClass(object):
    def __init__(self):
        self.foo = 'foo'
        self.bar = 1.1
        self.parent = ParentClass(1)
Run Code Online (Sandbox Code Playgroud)

这应该导致JSON类似于以下内容:

{ '__ChildClass__': {
    'bar': 1.1,
    'foo': 'foo',
    'parent': {
        '__ParentClass__': {
            'foo': 1}
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*rov 9

在以下函数的帮助下,自定义类的实例可以表示为JSON格式的字符串:

def json_repr(obj):
  """Represent instance of a class as JSON.
  Arguments:
  obj -- any object
  Return:
  String that reprent JSON-encoded object.
  """
  def serialize(obj):
    """Recursively walk object's hierarchy."""
    if isinstance(obj, (bool, int, long, float, basestring)):
      return obj
    elif isinstance(obj, dict):
      obj = obj.copy()
      for key in obj:
        obj[key] = serialize(obj[key])
      return obj
    elif isinstance(obj, list):
      return [serialize(item) for item in obj]
    elif isinstance(obj, tuple):
      return tuple(serialize([item for item in obj]))
    elif hasattr(obj, '__dict__'):
      return serialize(obj.__dict__)
    else:
      return repr(obj) # Don't know how to handle, convert to string
  return json.dumps(serialize(obj))
Run Code Online (Sandbox Code Playgroud)

此函数将生成JSON格式的字符串

  • 自定义类的实例,

  • 一个字典,其中包含自定义类的实例,

  • 自定义类的实例列表