MST
星途 面试题库

面试题:Python中JSON序列化与反序列化的常见问题及处理

在Python中使用`json`模块进行数据序列化与反序列化时,常常会遇到一些问题,比如序列化自定义类对象。请举例说明如何处理这种情况,以及在反序列化时如何确保数据的正确性和安全性。
45.8万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

序列化自定义类对象

  1. 方法一:定义__dict__属性或to_dict方法 假设我们有一个简单的自定义类Person
import json


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


person = Person("Alice", 30)

如果直接使用json.dumps(person)会报错,因为json模块默认不知道如何处理自定义类对象。 我们可以给Person类添加一个to_dict方法,将对象转换为可序列化的字典:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def to_dict(self):
        return {
            "name": self.name,
            "age": self.age
        }


person = Person("Alice", 30)
serialized = json.dumps(person.to_dict())
print(serialized)
  1. 方法二:使用JSONEncoderdefault方法
import json


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


class CustomEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, Person):
            return {
                "name": o.name,
                "age": o.age
            }
        return super().default(o)


person = Person("Alice", 30)
serialized = json.dumps(person, cls=CustomEncoder)
print(serialized)

反序列化时确保数据的正确性和安全性

  1. 使用JSONDecoderobject_hook 假设我们从上述序列化得到的数据进行反序列化:
import json


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


def person_decode(dct):
    if "name" in dct and "age" in dct:
        return Person(dct["name"], dct["age"])
    return dct


serialized = '{"name": "Alice", "age": 30}'
deserialized = json.loads(serialized, object_hook=person_decode)
if isinstance(deserialized, Person):
    print(f"Name: {deserialized.name}, Age: {deserialized.age}")
  1. 数据验证person_decode函数中,除了检查必要的键是否存在,还可以进行类型验证等操作,比如:
def person_decode(dct):
    if "name" in dct and "age" in dct:
        if not isinstance(dct["name"], str):
            raise ValueError("Name should be a string")
        if not isinstance(dct["age"], int):
            raise ValueError("Age should be an integer")
        return Person(dct["name"], dct["age"])
    return dct
  1. 限制反序列化的数据类型 只反序列化特定结构的数据,避免恶意数据构造复杂对象进行攻击。例如,只允许反序列化简单的字典、列表、字符串、数字等基本类型组成的结构,对于复杂的对象构造(如利用__import__等危险操作)进行防范。在object_hook函数中,对传入的字典结构进行严格检查,确保不会引入安全风险。