【问题标题】:Obtaining a JSON string from python list that contains sub-lists of objects?从包含对象子列表的python列表中获取JSON字符串?
【发布时间】:2020-08-23 15:18:21
【问题描述】:

我有一个像这样的名为 Data 的类:

class Data:

    def __init__(self, ticker, comments, submissions):
        self.ticker = ticker
        self.comments = comments
        self.submissions = submissions

其中tickerstringcommentsComment 类型的对象列表,submissionsSubmission 类型的对象列表。 CommentSubmission 有自己的字段。

现在我有一个 Data 类型的对象列表

我想遍历列表并获取包含所有元素的 JSON 字符串并将其打印到文件中。

我的代码:

    json_string = json.dumps([ob.__dict__ for ob in data_list])
    f = open("data.json", "w")
    f.write(json_string)
    f.close()

这会引发类型错误:

TypeError: Object of type Comment is not JSON serializable

我不知道我在这里做错了什么,有人知道吗?

编辑:

评论类:

class Comment:

def __init__(self, author_name, body, ups):
    self.author_name = author_name
    self.body = body
    self.ups = ups

所有字段都是字符串/int

【问题讨论】:

  • Comment 类的外观如何?
  • 我添加到问题中

标签: python json python-3.x list


【解决方案1】:

使用default=lambda x: x.__dict__ 应该会对您有所帮助。它将转换任何不可序列化的对象,您不必修改很多以前的代码

import json
# rest of your code
with open("file.json", "w+", encoding="utf-8") as file:
    json.dump(datalist, file, default=lambda x: x.__dict__) #datalist is a list in my case

编辑:

这是我测试时的完整代码:

import json
class Data:
    def __init__(self, ticker="string", comment=[], submissions=[]):
        self.ticker = ticker
        self.comments = comments
        self.submissions = submissions


class Comment:
    def __init__(self, author_name="", body="", ups=1):
        self.author_name = author_name
        self.body = body
        self.ups = ups

class Submission:
    def __init__(self, author_name="", body="", ups=1):
        self.author_name = author_name
        self.body = body
        self.ups = ups

comments = [Comment(ups=i) for i in range(10)]
submissions = [Submission(ups=2*i) for i in range(10)]

datalist = [Data(comment=comments, submissions=submissions) for i in range(5)]

with open("file.json", "w+", encoding="utf-8") as file:
    json.dump(datalist, file, default=lambda x: x.__dict__)

【讨论】:

    【解决方案2】:

    默认情况下不能序列化类。所以要么你必须手动序列化它,就像你对Data类做的一样,或者使用自定义的json编码器。

    手动:

    class Data:
       ...
       def to_json(self):
           res = self.__dict__
           res['comments'] = self.comments.__dict__
           return res
    

    但是这个解决方案不是很灵活,所以宁愿使用一个自定义的 JSON 编码器,它会自动处理它在序列化过程中遇到的所有对象:

    # from top of my head something like this:
    from json import JSONEncoder
    class MyEncoder(JSONEncoder):
        def default(self, o):
            # handle instance of `Data` during json.dump 
            if isinstance(o, Data):
                 return o.__dict__
            # handle instance of `Comment` during json.dump
            if isinstance(o, Comment):
                 return o.__dict__
    
            return super().default(o)
    
    
    json.dumps(data_list, cls=MyEncoder) # custom encoder should handle it
    

    【讨论】:

      猜你喜欢
      • 2015-11-11
      • 1970-01-01
      • 2019-03-19
      • 1970-01-01
      • 2020-03-24
      • 1970-01-01
      • 1970-01-01
      • 2016-04-15
      • 1970-01-01
      相关资源
      最近更新 更多