В Python ошибка “TypeError: Object of type set is not JSON serializable” происходит, когда мы пытаемся конвертировать свойство ‘set‘ объекта в строку JSON.
Чтобы убрать эту ошибку надо преобразовать ‘set
‘ в список, прежде чем сериализовать его в JSON, например так json.dumps(list(my_set))
.
Вот пример того, как возникает ошибка:
import json
my_set = {'a', 'b', 'c', 'd'}
# ⛔️ TypeError: Object of type set is not JSON serializable
json_str = json.dumps(my_set)
Мы попытались передать заданное свойство ‘set‘ объекта методу json.dumps(), но этот метод не обрабатывает заданные объекты по умолчанию.
Конвертирование объекта set
в list
для устранения ошибки
Для устранения ошибки, используйте встроенный класс list() для преобразования набора в список перед его сериализацией.
import json
my_set = {'a', 'b', 'c', 'd'}
json_str = json.dumps(list(my_set))
print(json_str) # '["b", "c", "a", "d"]'
print(type(json_str)) # <class 'str'>
По умолчанию JSON обрабатывает значения списка, но мы можем использовать собственный список Python вместо набора при сериализаций.
Метод json.dumps преобразует объект Python в строку формата JSON.
Создание класса SetEncoder
для устранения ошибки
В качестве альтернативы вы можете расширить класс JSONEncoder обрабатывать преобразования в методе default.
import json
class SetEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj)
return json.JSONEncoder.default(self, obj)
my_set = {'a', 'b', 'c', 'd'}
json_str = json.dumps(my_set, cls=SetEncoder)
print(json_str) # 👉️ '["b", "c", "a", "d"]'
print(type(json_str)) # 👉️ <class 'str'>
Мы унаследовались от класса JSONEncoder.
Класс JSONEncoder по умолчанию поддерживает следующие объекты и типы.
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int and float derived Enums | number |
True | true |
False | false |
None | null |
Обратите внимание, что класс JSONEncoder не поддерживает преобразование set в JSON по умолчанию.
Мы можем справиться с этим, наследованием от класса и реализовав метод default(), который возвращает сериализуемый объект.
import json
class SetEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj)
return json.JSONEncoder.default(self, obj)
Если переданное значение является set, мы преобразуем его в list и возвращаем результат.
Функция isinstance() возвращает значение True, если переданный объект является экземпляром или подклассом переданного класса.
Чтобы использовать собственный JSONEncoder, укажите его с именованным аргументом cls в вашем вызове метода json.dumps().
import json
class SetEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj)
return json.JSONEncoder.default(self, obj)
my_set = {'a', 'b', 'c', 'd'}
# ✅ pass cls keyword argument
json_str = json.dumps(my_set, cls=SetEncoder)
print(json_str) # 👉️ '["b", "c", "a", "d"]'
print(type(json_str)) # 👉️ <class 'str'>
Если вы не укажете cls kwarg, то будет использоваться JSONEncoder по умолчанию.
Использование аргумента default для устранения ошибки
Вы также можете использовать аргумент default при вызове метода json.dumps().
import json
my_set = {'a', 'b', 'c', 'd'}
json_str = json.dumps(my_set, default=list)
print(json_str) # ["c", "d", "b", "a"]
print(type(json_str)) # <class 'str'>
Метод json.dumps преобразует объект Python’a в строку в формате JSON.
Мы просто преобразуем объект set в list, передав его классу list.
Вы также можете определить пользовательскую функцию сериализатора JSON.
import json
my_set = {'a', 'b', 'c', 'd'}
def json_serializer(value):
if isinstance(value, set):
return list(value)
return value
json_str = json.dumps(my_set, default=json_serializer)
print(json_str) # ["a", "d", "b", "c"]
print(type(json_str)) # <class 'str'>
Мы устанавливаем именованный аргумент default для пользовательской функции json_serializer.
Функция json_serializer использует метод isinstance(), чтобы проверить, является ли значение набором.
Если значение представляет собой набор, мы преобразуем его в список и возвращаем результат. В противном случае значение возвращается как есть.
Использование модуля simplejson для устранения ошибки
Альтернативный способ устранения ошибки — это использование модуля simplejson.
Вы можете установить модуль, выполнив следующую команду из своего терминала.
pip install simplejson
# 👇️ или pip3
pip3 install simplejson
Теперь вы можете использовать метод simplejson.dumps() для сериализации заданного объекта.
import simplejson as json
my_set = {'a', 'b', 'c', 'd'}
json_str = json.dumps(my_set, iterable_as_array=True)
print(json_str) # ["b", "c", "d", "a"]
print(type(json_str)) # <class 'str'>
Обратите внимание, что мы импортировали simplejson и присвоили ему псевдоним json.
Когда именованный аргумент iterable_as_array имеет значение True, объекты, которые не могут быть преобразованы в JSON по умолчанию, но реализуют метод __iter__(), кодируются как массив JSON.
Это именно то, что нам нужно для преобразования набора в JSON.