Opened 4 years ago

Closed 4 years ago

#32079 closed Bug (invalid)

Using JSONField with Func() crash when returns boolean.

Reported by: Loic Quertenmont Owned by: nobody
Component: Database layer (models, ORM) Version: 3.1
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Hello,

I've jsut migrated to django 3 and I observed a bug when annotating a json field

I have a model with a json field named "references" which is basically a dictionnary,
If I annotate this field using a jsonb_path_exists function through a "Func" as shown bellow
and I then try to fetch or iterate over the results, it crashes in from_db_value (django/db/models/fields/json.py)
because it tries to decode the boolean output of this function via json.loads

           qs = qs.annotate(reference_match = Func(F('references'), ('$.* ? (%s)'%condition, ) , function='jsonb_path_exists')         
           print(list(qs)) # fails

changing the line to (adding the output_field of the function) is enough to make it work

           qs = qs.annotate(reference_match = Func(F('references'), ('$.* ? (%s)'%condition, ) , function='jsonb_path_exists',, output_field=models.BooleanField())         
           print(list(qs)) # success

This was not needed in django 2.2.X
Here it seems to believe that the Func has the same time has the referenced field.

Thanks in advance for fixing this.
Loic

PS: I am runnong on postgresql 12

Change History (1)

comment:1 by Mariusz Felisiak, 4 years ago

Resolution: invalid
Status: newclosed
Summary: 3.1.2 postgresql and JsonField annotationUsing JSONField with Func() crash when returns boolean.

Thanks for this report. It works in Django < 3.1.1 but not intentionally. Func() guesses an output type based on expressions types, in this case JSONField, PostgreSQL supports primitives in jsonb data type so it treats the result of jsonb_path_exists() as a JSONField. As a consequence of #31956, fetching a JSONField should return a string instead of pre-loaded data that's why it crashes.

I don't think there is anything to fix here, you want to use jsonb_path_exists() which takes JSON and returns boolean, so passing output_field=models.BooleanField() should be necessary.

Note: See TracTickets for help on using tickets.
Back to Top