#34144 closed Bug (invalid)
Casting a string inside a JSONField into an integer does not work on PostgreSQL
Reported by: | Clément Escolano | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 4.1 |
Severity: | Normal | Keywords: | postgresql, jsonfield, cast |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Hello
When casting an integer represented as a string inside a JSONField on PostgreSQL, there is the following error:
django.db.utils.DataError: cannot cast jsonb string to type integer
It works with a SQLite database.
To reproduce the error, you can create a simple model with a JSONField:
class MyModel(models.Model): data = models.JSONField() MyModel.objects.create(data={"value": "3"}) MyModel.objects.annotate(actual_value=Cast("data__value", output_field=IntegerField())).first()
The produced query is the following:
SELECT "myapp_mymodel"."id", "myapp_mymodel"."data", (("myapp_mymodel"."data" -> 'value'))::integer AS "actual_value" FROM "myapp_mymodel" LIMIT 1;
This stackoverflow question hints that adding an extra ">" after "->" fixes it and indeed the following query returns the correct result:
SELECT "myapp_mymodel"."id", "myapp_mymodel"."data", (("myapp_mymodel"."data" ->> 'value'))::integer AS "actual_value" FROM "myapp_mymodel" LIMIT 1;
Change History (3)
comment:1 by , 2 years ago
Description: | modified (diff) |
---|
comment:2 by , 2 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:3 by , 2 years ago
Thank you for the information and the method on how to solve my problem.
It would have been great that django automatically uses this method (when using the Cast method, I expect the casting to not have issues) but I assume this is for a good reason.
I don't think there is much we can do 🤔 as this is a PostgreSQL caveat. On Django 4.2+ you will be able to use the
KT()
expression (see docs), e.g.on Django < 4.2 you can use the
KeyTextTransform()
expression, e.g.