面试题答案
一键面试报错原因
json.dumps
只能序列化基本数据类型(如字典、列表、字符串、数字、布尔值、None
),而自定义类 MyClass
的实例不属于这些基本类型,所以直接调用会报错。
方案一:转换为字典
- 实现方式:
import json
class MyClass:
def __init__(self):
self.attr1 = 'value1'
self.attr2 = 42
obj = MyClass()
data_dict = {
'attr1': obj.attr1,
'attr2': obj.attr2
}
json_str = json.dumps(data_dict)
print(json_str)
- 优点:
- 简单直接,容易理解和实现。
- 不需要额外的复杂操作,对于简单的自定义类很适用。
- 缺点:
- 如果类中有很多属性,手动构建字典会很繁琐,容易出错。
- 对于类中属性结构复杂(如嵌套自定义类等)的情况,处理起来比较困难。
方案二:使用 __dict__
属性
- 实现方式:
import json
class MyClass:
def __init__(self):
self.attr1 = 'value1'
self.attr2 = 42
obj = MyClass()
json_str = json.dumps(obj.__dict__)
print(json_str)
- 优点:
- 代码简洁,一行代码即可实现序列化,对于属性较多的类也很方便。
- 自动包含所有实例属性,无需手动列举每个属性。
- 缺点:
- 可能会序列化一些不希望被序列化的内部属性(如果类中定义了以双下划线开头的私有属性,在 Python 中实际上是会变形为
_ClassName__attr
形式存在于__dict__
中的)。 - 对于类中属性是复杂类型(如自定义类对象),仍然无法直接序列化,需要进一步处理。
- 可能会序列化一些不希望被序列化的内部属性(如果类中定义了以双下划线开头的私有属性,在 Python 中实际上是会变形为
方案三:自定义 JSONEncoder
- 实现方式:
import json
class MyClass:
def __init__(self):
self.attr1 = 'value1'
self.attr2 = 42
class MyEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, MyClass):
return {
'attr1': o.attr1,
'attr2': o.attr2
}
return super().default(o)
obj = MyClass()
json_str = json.dumps(obj, cls=MyEncoder)
print(json_str)
- 优点:
- 更加灵活,可以根据需要定制序列化逻辑,适用于各种复杂的自定义类结构。
- 可以处理不同类型的自定义类,通过
isinstance
判断并进行相应处理。
- 缺点:
- 代码相对复杂,需要定义一个自定义的
JSONEncoder
类,增加了代码量。 - 如果类结构发生变化,需要修改
default
方法中的序列化逻辑,维护成本相对较高。
- 代码相对复杂,需要定义一个自定义的