« ^ »

DjangoのJSONField事情

所要時間: 約 2分

Django3ではJSONFieldがサポートされた。Django2までは、いろいろな JSONFieldがライブラリとして実装されており挙動とサポート範囲が異なって いた。それぞれのJSONFieldがMySQL上ではどのように定義されるのかを確認し た。

検証環境

ソフトウェアバージョン
PythonPython3.6
DatabaseMySQL 5.7

Django2

Django==2.2.13
django-jsonfield==1.4.0
mysqlclient==1.3.13
django-jsonfield-backport==1.0.4
requirements.txt

Django3

Django==3.2.8
mysqlclient==2.0.3
django-jsonfield==1.4.1
django-jsonfield-backport==1.0.4
requirements.txt

model

Fooというモデルを定義し、それぞれのJSONFieldを用いたカラムを定義した。

カラム名Fieldクラス備考
the_jsondjango-jsonfield.JSONField
native_jsondjango.db.models.JSONFieldDjango2では使用不可
backport_jsondjango_jsonfield_backport.models.JSONField
from django.db import models

import jsonfield
from django_jsonfield_backport import models as backport


class Foo(models.Model):
    the_json = jsonfield.JSONField()
    native_json = models.JSONField()
    backport_json = backport.JSONField()
foo/models.py

(jango3版のモデル定義)

MySQLでのテーブル定義

django-jsonfield.JSONFieldはMySQL上ではlogntxt型で定義される。 django.db.models.JSONFieldはMySQL上ではjson型で定義される。 django_jsonfield_backport.models.JSONFieldはdjango.db.models.JSONField のバックポート版なのでjson型で定義される。

django-jsonfield.JSONFieldをdjango.db.models.JSONFieldに変更すると MySQL上の型も変わってしまうので型の変更及びデータ自体も変更になる。

Python上の型MySQL上の型
django-jsonfield.JSONFieldlongtext
django.db.models.JSONFieldjson
django_jsonfield_backport.models.JSONFieldjson
show create table foo_foo;
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table   | Create Table                                                                                                                                                                                                                                   |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| foo_foo | CREATE TABLE `foo_foo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `the_json` longtext NOT NULL,
  `native_json` json NOT NULL,
  `backport_json` json NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

MySQLのjson型

MySQL上でのjson型は次のような振る舞いをする

  • JSON 値は文字列として書き込まれる。
  • JSONドキュメントの格納に必要な領域はLONGBLOBやLONGTEXTとほぼ同じとなる。
  • JSON値を必要とするコンテキストで使用される文字列を解析し、JSONとして有効でない場合はエラーを生成する。
  • MySQL 8.0.13より前は、NULL以外のデフォルト値を含めることはできない。

https://dev.mysql.com/doc/refman/8.0/ja/json.html