Python类序列化问题:如何将嵌套类对象转为JSON对象而非字符串
解决Python类对象转JSON时嵌套对象变为字符串的问题
问题根源
你当前的实现中,toJSON()方法通过json.dumps将单个类对象转换为JSON字符串,把这类字符串赋值给WorkOrder的属性后,最终整体序列化时,这些字符串会被当成普通文本处理,被转义成带双引号的字面量,而非解析为JSON对象。
解决方案
以下是几种可行的修正方式:
方法一:统一序列化时处理所有自定义类
去掉类中的toJSON方法,直接创建类对象,在最终序列化时通过default参数统一将自定义类转为字典:
import datetime as dt import json class StatusDetails: def __init__(self, Description, Value): self.Description = Description self.Value = Value class OrderRef: def __init__(self, ID, Name): self.ID = ID self.Name = Name class WorkOrder: def __init__(self, statusDetails, orderRef, RequestedDate): self.RequestedDate = RequestedDate self.StatusDetails = statusDetails self.OrderRef= orderRef listOfWO = [] # 直接创建类对象,不转成字符串 _statusDetails = StatusDetails("OPEN", "OPEN") _orderRef = OrderRef('12345', 'SOME VALUE') _requestedDate = dt.datetime.now('US/Central').isoformat() _wo = WorkOrder(_statusDetails, _orderRef, _requestedDate ) listOfWO.append(_wo) # 序列化时用default参数处理所有自定义类 _WorkOrderString = json.dumps(listOfWO, default=lambda o: o.__dict__, indent=4) print('posting workorder json: \n' + _WorkOrderString )
方法二:让类返回字典而非JSON字符串
修改类的方法,将toJSON改为返回对象的字典形式,再传入WorkOrder:
import datetime as dt import json class StatusDetails: def __init__(self, Description, Value): self.Description = Description self.Value = Value def to_dict(self): return self.__dict__ class OrderRef: def __init__(self, ID, Name): self.ID = ID self.Name = Name def to_dict(self): return self.__dict__ class WorkOrder: def __init__(self, statusDetails, orderRef, RequestedDate): self.RequestedDate = RequestedDate self.StatusDetails = statusDetails self.OrderRef= orderRef listOfWO = [] # 调用to_dict获取字典,而非JSON字符串 _statusDetails = StatusDetails("OPEN", "OPEN").to_dict() _orderRef = OrderRef('12345', 'SOME VALUE').to_dict() _requestedDate = dt.datetime.now('US/Central').isoformat() _wo = WorkOrder(_statusDetails, _orderRef, _requestedDate ) listOfWO.append(_wo) # 直接序列化字典结构即可 _WorkOrderString = json.dumps([ob.__dict__ for ob in listOfWO], indent=4) print('posting workorder json: \n' + _WorkOrderString )
方法三:自定义JSON编码器(适合复杂场景)
继承json.JSONEncoder实现自定义编码逻辑,灵活处理不同类型的对象:
import datetime as dt import json class StatusDetails: def __init__(self, Description, Value): self.Description = Description self.Value = Value class OrderRef: def __init__(self, ID, Name): self.ID = ID self.Name = Name class WorkOrder: def __init__(self, statusDetails, orderRef, RequestedDate): self.RequestedDate = RequestedDate self.StatusDetails = statusDetails self.OrderRef= orderRef # 自定义编码器 class CustomEncoder(json.JSONEncoder): def default(self, o): # 处理自定义类 if isinstance(o, (StatusDetails, OrderRef, WorkOrder)): return o.__dict__ # 额外处理datetime类型(如果需要) if isinstance(o, dt.datetime): return o.isoformat() return super().default(o) listOfWO = [] _statusDetails = StatusDetails("OPEN", "OPEN") _orderRef = OrderRef('12345', 'SOME VALUE') _requestedDate = dt.datetime.now('US/Central').isoformat() _wo = WorkOrder(_statusDetails, _orderRef, _requestedDate ) listOfWO.append(_wo) # 序列化时指定自定义编码器 _WorkOrderString = json.dumps(listOfWO, cls=CustomEncoder, indent=4) print('posting workorder json: \n' + _WorkOrderString )
效果说明
以上三种方法都能让StatusDetails和OrderRef在最终的JSON输出中以JSON对象形式呈现,而非转义后的字符串字面量。
内容的提问来源于stack exchange,提问作者SoftwareDveloper
相关产品推荐
相关产品推荐

