如何将Python对象序列化为JSON?

3
I希望您能够将一个Python对象序列化,然后保存到MySQL(基于Django ORM),我想获取它并将此对象传递给需要此类对象作为参数的函数。
以下是我的主要逻辑代码的两个部分:
1.保存参数部分:


class Param(object):
    def __init__(self, name=None, targeting=None, start_time=None, end_time=None):
        self.name = name
        self.targeting = targeting
        self.start_time = start_time
        self.end_time = end_time
    #...

param = Param()
param.name = "name1"
param.targeting= "targeting1"


task_param = {
            "task_id":task_id,              # string
            "user_name":user_name,          # string
            "param":param,                  # Param object
            "save_param":save_param_dict,   # dictionary
            "access_token":access_token,    # string
            "account_id": account_id,       # string
            "page_id": page_id,             # string
            "task_name":"sync_create_ad"    # string
        }


class SyncTaskList(models.Model):
    task_id = models.CharField(max_length=128, blank=True, null=True)
    ad_name = models.CharField(max_length=128, blank=True, null=True)
    user_name = models.CharField(max_length=128, blank=True, null=True)
    task_status = models.SmallIntegerField(blank=True, null=True)
    task_fail_reason = models.CharField(max_length=255, blank=True, null=True)
    task_name = models.CharField(max_length=128, blank=True, null=True)
    start_time = models.DateTimeField()
    end_time = models.DateTimeField(blank=True, null=True)
    task_param = models.TextField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'sync_task_list'



SyncTaskList(
                task_id=task_id,
                ad_name=param.name,
                user_name=user_name,
                task_status=0,
                task_param = task_param,
            ).save()


2 使用 param 部分。

def add_param(param, access_token):
    pass

task_list = SyncTaskList.objects.filter(task_status=0)
for task in task_list:
    task_param = json.loads(task.task_param)
    add_param(task_param["param"], task_param["access_token"]) # pass param object to function add_param


如果我直接使用Django ORM将task_param保存到mysql中,会出现错误。
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

在ORM操作之后,我得到一个字符串,其中属性名用单引号括起来,例如:


# in mysql it saved as 

 task_param: " task_param: {'task_id': 'e4b8b240cefaf58fa9fa5a591221c90a',
              'user_name': 'jimmy',
              'param': Param(name='name1',
                                    targeting='geo_locations',
                                   ),
              'save_param': {}}"


我现在对Python对象的序列化感到困惑,不知道如何加载原始对象并将其传递给函数?

欢迎任何评论。非常感谢。

更新了我目前的解决方案

task_param = {
            # ...
            "param":vars(param),            # turn Param object to dictionary 
            # ...
            }

SyncTaskList(
                #...
                task_param = json.dumps(task_param),
                #...
            ).save()

#task_list = SyncTaskList.objects.filter(task_status=0)
#for task in task_list:
    task_param = json.loads(task.task_param)
    add_param(Param(**task_param["param"]), task_param["access_token"])

根据 @AJS 的回答更新

直接使用 pickle dumps 并将其保存为一个二进制字段,然后使用pickle loads也可正常工作


有更好的解决方案吗?

如果我理解正确的话,在MySql中,您将task_param作为字符串保存在task_param列下,并使用单引号保存它。如果我错了,请纠正我。 - AJS
使用 json.dumps(obj)obj 转换为 JSON。 - Klaus D.
@KlausD。它会引发错误 TypeError: Object of type 'Param' is not JSON serializable - jia Jimmy
@AJS 是的,如果我直接保存为上面代码所示的样式,它会自动转换为单引号风格。 - jia Jimmy
obj 必须是一个简单的 Python 结构,由内置类型如字典、列表、字符串、数字等组成。而你的 param 键不是这样的。 - Klaus D.
谢谢您的回复,您的意思是我应该根据obj的属性将其转换为键值字典吗? - jia Jimmy
2个回答

1

0
你可以使用pickle,基本上是将你的Python对象序列化并以字节形式保存在MySQL数据库中,使用BinaryField作为Django模型字段类型。我认为在你的情况下JSON序列化不起作用,因为你的字典值中也有一个Python对象。当你从数据库中获取数据时,只需取消pickle即可,语法类似于json库,请参见下文。
import pickle
#to pickle
data = pickle.dumps({'name':'testname'})
# to unpickle just do
pickle.loads(data)

所以在您的情况下,当您取消pickle对象时,您应该以与pickle之前相同的形式获取数据。

希望这可以帮助到您。


谢谢您的回复,使用pickle.dump后我可以得到一个字节数据,但是当我通过Django ORM将其保存到mysql时,它变成了一个字符串,我无法再次加载它。 - jia Jimmy
使用 pickle.dumps 应该返回一个字符串,你漏掉了 s - AJS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接