自定义 JSON 编码器引发 "Object not JSON serializable" 错误
Custom JSON Encoder raises "Object not JSON serializable" error
我正在尝试为我的 class 之一创建自定义 JSON 编码器。
我创建了一个 simplified version 来尝试该方法并且它有效,但是当我在我的项目中应用该方法时它不断抛出错误:
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
我要转换的对象是BeautifulSoupTag
class的修改版本,class的代码如下:
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
HTML书签class继承自节点:
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 在评论中建议的 link 到工作 code sample and html input 的
你好像打错了:def defaut(self, o):
应该是 def default(self, o):
我正在尝试为我的 class 之一创建自定义 JSON 编码器。 我创建了一个 simplified version 来尝试该方法并且它有效,但是当我在我的项目中应用该方法时它不断抛出错误:
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
我要转换的对象是BeautifulSoupTag
class的修改版本,class的代码如下:
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
HTML书签class继承自节点:
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.
HTMLBookmark
对象
如果需要任何进一步的信息,请告诉我,谢谢 :)。
编辑:
这是@Ulrich Eckhardt 在评论中建议的 link 到工作 code sample and html input 的
你好像打错了:def defaut(self, o):
应该是 def default(self, o):