Данные Django JSONField с целочисленными ключами
Я хочу сохранить экземпляр модели с JSON диктом с целочисленными ключами, например {2: 3}.
Но после сохранения мой dict превращается в {"2": 3}. Есть ли способ сохранить целочисленные ключи в JSON?
class MyModel(models.Model):
data = JSONField("data")
record = MyModel.objects.create(
data={2: 3},
)
record.refresh_from_db()
print(record.data)
# > {"2": 3}
# And I want record.data == {2: 3}
Поведение одинаково для from django.contrib.postgres.fields import JSONField и для современных from django.db.models import JSONField
Я хочу сохранить экземпляр модели с диктой JSON с целочисленными ключами, как
{2: 3}.
Это невозможно: спецификации JSON гласят, что ключи - это всегда строки. Сериализатор JSON в Python преобразует ключи в их строковые аналоги (возможно, в этом случае уместнее было бы выдать ошибку).
Если все ключи являются целыми числами, вы можете создать подкласс JSONField, который будет автоматически приводить ключи к ints, например:
from django.db.models import JSONField
def outer_json_is_object(value):
if not isinstance(value, dict):
raise ValidationError(_('Outer JSON item should be an object'), code='invalid_json_object')
class IntKeyJSONField(JSONField):
def __init__(self, *args, **kwargs):
validators = kwargs.setdefault('validators', [])
validators.append(outer_json_is_object)
super().__init__(*args, **kwargs)
def from_db_value(self, value, expression, connection):
value = super().from_db_value(value, expression, connection)
if value is not None:
return { int(k): v for k, v in value.items() }
то он приведет внешние ключи к ints объекта JSON. Таким образом, вы можете использовать IntKeyJSONField, но при этом не хранит ключи как целые числа, поскольку, опять же, это просто не правильный JSON, что мы делаем, так это постобрабатываем словарь при чтении из JSON и таким образом заменяем ключи их int аналогами.