尝试JSON转储时,嵌套类无法在python中序列化

时间:2018-08-08 17:57:27

标签: json dictionary serialization

我目前在Python中有两个这样的类

class person:
    age=""
    name=""
    ranking = {}

    def addRanking():
    #Do Whatever treatment and add to the ranking dict

class ranking:
    semester = ""
    position = ""
    gpa = ""

我有一个名为dictP json.dumps()的字典,但似乎没有用。这是我转储到JSON的函数

def toJson():
    jsonfile = open('dict.json', 'w')
    print(json.dump(listP, jsonfile))

我很有名:不是JSON可序列化的。

您知道我可以做些什么来解决这个问题。我认为拥有两个可序列化的字典可以避免这种问题,但显然不会。

预先感谢

编辑:

这里有个例子(抱歉,我在手机上打错了打字,我不确定它是否可以运行,但是您可以理解)

class person:
    age=""
    name=""
    ranking = {}

    def __init__(self, age, name):
        self.age = age
        self.name = name
        self.ranking = {}

    def addRanking(self,semester,position,gpa):
        #if the semester is not already present in the data for that person
            self.ranking[semester] = make_ranking(semester,position,gpa)

class ranking:
    semester = ""
    position = ""
    gpa = ""

    def __init__(self, semester, position, gpa):
        self.semester = semester
        self.position = position
        self.gpa = gpa

dictP = {}


def make_person(age, name):
    # Some stuff happens there
    return person(age,name)

def make_ranking(semester,postion,gpa):
    #some computation there
    return ranking(semester,position,gpa)

def pretending_to_read_csv():
    age = 12
    name = "Alice"
    p = make_person(age, name)
    dictP["1"] = p

    age = 13
    name = "Alice"
    p = make_person(age, name)
    dictP["2"] = p

    #We read a csv for ranking that gives us an ID 
    semester = 1
    position = 4 
    gpa = 3.2
    id = 1 

    dictP["1"].addRanking(semester, position, gpa)

    semester = 2
    position = 4 
    gpa = 3.2
    id = 1 

    dictP["1"].addRanking(semester, position, gpa)

2 个答案:

答案 0 :(得分:1)

您可以尝试在实例的json.dump成员上调用.__dict__。您说您有一个人员实例列表,因此请尝试执行以下操作:

listJSON = []
for p in listP
    #append the value of the dictionary containing data about your person instance to a list
    listJSON.append(p.__dict__)
json.dump(listJSON, jsonfile)

如果您将个人实例存储在字典中,例如:dictP = {'person1': p1, 'person2': p2},则此解决方案将遍历键并将其对应的值更改为实例的__dict__成员:

for key in dictP:
    dictP[key] = dictP[key].__dict__
json.dump(dictP, jsonfile)

答案 1 :(得分:1)

要使字典可序列化,请注意,该字典中的所有键和值也必须可序列化。您没有向我们展示listP包含的内容,但我猜是这样的:

>>> listP
[<__main__.person instance at 0x107b65290>, <__main__.person instance at 0x107b65368>]

Python实例不可序列化。

我认为您想要一个字典列表,如下所示:

>>> listP
[{'ranking': {}, 'age': 10, 'name': 'fred'}, {'ranking': {}, 'age': 20, 'name': 'mary'}]

这将按您的预期进行序列化:

>>> import json
>>> json.dumps(listP)
'[{"ranking": {}, "age": 10, "name": "fred"}, {"ranking": {}, "age": 20, "name": "mary"}]'

更新

(感谢添加示例代码。)

>>> pretending_to_read_csv()
>>> dictP
{'1': <__main__.person instance at 0x107b65368>, '2': <__main__.person instance at 0x107b863b0>}

回想一下,用户定义的类不能自动序列化。可以直接扩展JSONEncoder来处理这些情况,但是您真正需要的只是一个函数,它可以将您的对象变成一个完全由基元组成的字典。

def convert_ranking(ranking):
    return {
        "semester": ranking.semester,
        "position": ranking.position,
        "gpa": ranking.gpa}

def convert_person(person):
    return {
        "age": person.age,
        "name": person.name,
        "ranking": {semester: convert_ranking(ranking) for semester, ranking in person.ranking.iteritems()}}

再进行一次字典理解即可真正完成转换,一切就绪:

>>> new_dict = {person_id: convert_person(person) for person_id, person in dictP.iteritems()}
>>> from pprint import pprint
>>> pprint(new_dict)
{'1': {'age': 12,
       'name': 'Alice',
       'ranking': {1: {'gpa': 3.2, 'position': 4, 'semester': 1},
                   2: {'gpa': 3.2, 'position': 4, 'semester': 2}}},
 '2': {'age': 13, 'name': 'Alice', 'ranking': {}}}

由于其中没有填充用户定义的对象,因此将按您希望的那样进行序列化:

>>> json.dumps(new_dict)
'{"1": {"ranking": {"1": {"position": 4, "semester": 1, "gpa": 3.2}, "2": {"position": 4, "semester": 2, "gpa": 3.2}}, "age": 12, "name": "Alice"}, "2": {"ranking": {}, "age": 13, "name": "Alice"}}'