簡體   English   中英

自定義 JSON 編碼器引發“對象不可 JSON 序列化”錯誤

[英]Custom JSON Encoder raises "Object not JSON serializable" error

我正在嘗試為我的一個類創建自定義 JSON 編碼器。 我創建了一個簡化版本來嘗試該方法並且它有效,但是當我在我的項目中應用該方法時,它不斷拋出錯誤:

    json.dump(obj=self.tree, fp=f, cls=BookmarkEncoder, ensure_ascii=False)
  File "/usr/lib/python3.8/json/__init__.py", line 179, in dump
    for chunk in iterable:
  File "/usr/lib/python3.8/json/encoder.py", line 438, in _iterencode
    o = _default(o)
  File "/usr/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type HTMLBookmark is not JSON serializable

我嘗試轉換的對象是BeautifulSoup Tag類的修改版本,該類的代碼如下:

class HTMLBookmark(Tag, Node):
    """TreeBuilder class, used to add additional functionality to the
    BeautifulSoup Tag class. The following functionality is added:

    - add id to each folder("h3")/url("a") being imported
    - add property access to the Tag class' attributes
      (date_added, icon, icon_uri, id, index, title, type and url)
      which are usually found in the 'self.attrs' dictionary.
    - add a setter for (id, index and title)
    - redirect the self.children from an iterator iter(self.contents)
    to a list (self.contents) directly"""

    counter = itertools.count(start=2)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.name in ("a", "h3"):
            if not self.attrs.get("id"):
                self.attrs["id"] = next(__class__.counter)

    @property
    def date_added(self):
        date_added = self.attrs.get("add_date")
        if not date_added:
            date_added = round(time.time() * 1000)
        return int(date_added)

    @property
    def icon(self):
        return self.attrs.get("icon")

    @property
    def icon_uri(self):
        return self.attrs.get("iconuri")

    @property
    def id(self):
        return self.attrs.get("id")

    @id.setter
    def id(self, new_id):
        self.attrs["id"] = new_id

    @property
    def index(self):
        return self.attrs.get("index")

    @index.setter
    def index(self, new_index):
        self.attrs["index"] = new_index

    @property
    def title(self):
        return self.attrs.get("title")

    @title.setter
    def title(self, new_title):
        self.attrs["title"] = new_title

    @property
    def type(self):
        if self.name == "h3":
            return "folder"
        elif self.name == "a":
            return "url"

    @property
    def url(self):
        return self.attrs.get("href")

    @property
    def children(self):
        """To standardize the access of children amongst the different
        classes."""
        return self.contents

HTMLBookmark 類繼承自 Node:

class Node:
    def create_folder_as_json(self):
        folder = {
            "type": self.type,
            "id": self.id,
            "index": self.index,
            "parent_id": self.parent_id,
            "title": self.title,
            "date_added": self.date_added,
            "children": [],
        }
        return folder

    def create_url_as_json(self):
        url = {
            "type": self.type,
            "id": self.id,
            "index": self.index,
            "parent_id": self.parent_id,
            "title": self.title,
            "date_added": self.date_added,
            "url": self.url,
            "icon": self.icon,
            "iconuri": self.icon_uri,
            "tags": self.tags,
        }
        return url

    def __repr__(self):
        return f"{self.title} - {self.type} - id: {self.id}"

這是我的自定義編碼器

class BookmarkEncoder(json.JSONEncoder):
    def defaut(self, o):
        if isinstance(o, HTMLBookmark):
            if o.type == "folder":
                return o.create_folder_as_json()
            elif o.type == "url":
                return o.create_url_as_json()
        return json.JSONEncoder.default(self, o)

最后這是觸發錯誤的代碼:

with open(output_file, "w", encoding="Utf-8") as f:
    json.dump(obj=self.tree, fp=f, cls=BookmarkEncoder, ensure_ascii=False)

其中self.tree是通過使用 BeautifulSoup 導入 HTML 文件創建的HTMLBookmark對象。

如果需要任何進一步的信息,請告訴我,謝謝:)。

編輯:

這是@Ulrich Eckhardt 在評論中建議的工作代碼示例html 輸入的鏈接。

看起來你有一個錯字: def defaut(self, o):應該是def default(self, o):

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM