Python中如何实现JSON到Object的序列化和反序列化?

之前写 py 关于 JSON 的序列化都是用字典来操作,比较不方便,今儿实现下 json->object 的序列化方式,发现还挺方便,分享给大家。py 菜鸟,大佬轻喷。。。使用方法如下:

核心类:

class JsonClass(object):
def to_json_string(self):
    return json.dumps(self, default=lambda obj: obj.__dict__)

def from_json_string(self, json_string):
    data = json.loads(json_string)

    for key in self.__dict__.keys():
        setattr(self, key, data[key])

使用方法:

class Task(JsonClass):
    def __int__(self, id=None, name=None, timestamp=None):
        self.id = id
        self.name = name
        self.timestamp = timestamp

if name == ‘main’: # 序列化 task = Task(1, “a”, time.time()) print(task.to_json_string())

# 反序列化
json_string = '{"timestamp": 1560948789.5293133, "name": "a", "id": 1}'
task = Task()
task.from_json_string(json_string)


Python中如何实现JSON到Object的序列化和反序列化?

9 回复

搭配 py3.6 类型标记食用更佳


在Python里处理JSON和对象转换,直接用内置的json模块配合__dict__属性或者dataclasses就能搞定。

1. 基础方法:用__dict__属性 对于简单的类,序列化时用obj.__dict__转成字典,再用json.dumps();反序列化时先用json.loads()得到字典,然后手动传给类的构造器。

import json

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

# 序列化:对象 -> JSON字符串
user = User("Alice", 30)
json_str = json.dumps(user.__dict__)
print(json_str)  # 输出:{"name": "Alice", "age": 30}

# 反序列化:JSON字符串 -> 对象
data = json.loads(json_str)
new_user = User(data['name'], data['age'])
print(new_user.name)  # 输出:Alice

2. 更优雅的方法:用dataclassesdataclasses.asdict() Python 3.7+的dataclasses让这活儿更干净。用@dataclass装饰器定义类,序列化用dataclasses.asdict(),反序列化用解包字典。

import json
from dataclasses import dataclass, asdict

@dataclass
class Product:
    id: int
    name: str
    price: float

# 序列化
product = Product(1, "Laptop", 999.99)
json_str = json.dumps(asdict(product))
print(json_str)  # 输出:{"id": 1, "name": "Laptop", "price": 999.99}

# 反序列化
data = json.loads(json_str)
new_product = Product(**data)
print(new_product.name)  # 输出:Laptop

3. 处理复杂情况:自定义编码器/解码器 遇到日期、自定义类型等json默认不支持的,得自己写JSONEncoderobject_hook

import json
from datetime import datetime
from dataclasses import dataclass

@dataclass
class Event:
    name: str
    date: datetime

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()  # 把datetime转成ISO格式字符串
        return super().default(obj)

def custom_decoder(dct):
    if 'date' in dct:
        dct['date'] = datetime.fromisoformat(dct['date'])  # 把字符串转回datetime
    return dct

# 序列化
event = Event("Meeting", datetime.now())
json_str = json.dumps(asdict(event), cls=CustomEncoder)
print(json_str)

# 反序列化
data = json.loads(json_str, object_hook=custom_decoder)
new_event = Event(**data)
print(new_event.date)

简单说,普通对象用dataclasses最省事,复杂类型就自己写编码解码逻辑。

看标题还以为是自己写的解析,没想到还是调用的 api 😂

对比 字典 <–> json 的方式,是由性能优势?还是空间优势?

两点建议:

1. 类名叫 JsonSerializableMixin,否则看到类名 JsonClass 会觉得是个特别重大的功能;
2. from_json_string 改为 class method,因为 from_json_string 的意思其实是 create OBJECT from json string,所以由这个函数负责创建对象。如果函数名是类似 update_with_json_string 则没这个意义不明确的问题。

。。。鼓励一下

然而实质还是序列化和反序列化字典,因为字典是最接近 json 的结构的。lz 可以试一下这个,访问字典值如同访问对象属性。json.dumps 依旧有效。
https://stackoverflow.com/questions/4984647/accessing-dict-keys-like-an-attribute

尽管如此,我还是觉得 python 缺乏 struct 那样简单的构造数据的方法。

namedtuple 了解一下?

DRF 的序列化器了解一下

回到顶部