Python

TypeError: Объект типа не поддерживает JSON сериализацию

В 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 по умолчанию поддерживает следующие объекты и типы.

PythonJSON
dictobject
list, tuplearray
strstring
int, float, int and float derived Enumsnumber
Truetrue
Falsefalse
Nonenull

Обратите внимание, что класс 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.

To top