[Django] #37404: JSONIn with Value(None, JSONField()) does not match JSON null on Oracle

3 views
Skip to first unread message

Django

unread,
Oct 6, 2026, 2:27:07 PM (3 days ago) Oct 6
to django-...@googlegroups.com
#37404: JSONIn with Value(None, JSONField()) does not match JSON null on Oracle
-------------------------------------+-------------------------------------
Reporter: Clifford | Owner: Clifford Gama
Gama |
Type: Bug | Status: assigned
Component: Database | Version: 6.1
layer (models, ORM) | Keywords: json, oracle, null,
Severity: Normal | JSONIn
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
On Oracle, `JSONIn.as_oracle()`
[https://github.com/django/django/blob/8c34887b1ad8bb3ec61c6e713442dab3c643d557/django/db/models/fields/json.py#L462
only special-cases JSONNull()] on the right-hand side. A `Value(None,
output_field=JSONField())` is not routed to the same `JSON_EQUAL` path, so
it doesn't match a JSON `null` row in `__in`. Both `JSONNull()` and
`Value(None, JSONField())` match in `__exact`.

Failing test:

{{{#!diff
diff --git a/tests/model_fields/test_jsonfield.py
b/tests/model_fields/test_jsonfield.py
index 264b88a23d..2276b7857d 100644
--- a/tests/model_fields/test_jsonfield.py
+++ b/tests/model_fields/test_jsonfield.py
@@ -1076,6 +1076,15 @@ def test_in_json_whitespace(self):
[obj],
)

+ @skipUnlessDBFeature("supports_primitives_in_json_field")
+ @skipIfDBFeature("has_native_json_field")
+ def test_in_value_json_typed_none_matches_json_null(self):
+ json_null = NullableJSONModel.objects.create(value=JSONNull())
+ self.assertSequenceEqual(
+ NullableJSONModel.objects.filter(value__in=[Value(None,
JSONField())]),
+ [json_null],
+ )
+
def test_key_in(self):
tests = [
("value__c__in", [14], self.objs[3:5]),
}}}

Found while working on #37403, but the bug predates the introduction of
JSONIn or JSONNull, so it's not a regression in 6.1.
--
Ticket URL: <https://code.djangoproject.com/ticket/37404>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Oct 6, 2026, 3:19:48 PM (3 days ago) Oct 6
to django-...@googlegroups.com
#37404: JSONIn with Value(None, JSONField()) does not match JSON null on Oracle
-------------------------------------+-------------------------------------
Reporter: Clifford Gama | Owner: Clifford
| Gama
Type: Bug | Status: assigned
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: json, oracle, null, | Triage Stage: Accepted
JSONIn |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* stage: Unreviewed => Accepted
* version: 6.1 => 5.2

Comment:

Great, thank you!

I reproduced on 5.2 by replacing `JSONNull()` in the setup step with
`Value(None, JSONField())`. I got:
{{{
django.db.utils.DatabaseError: ORA-22848: cannot use NCLOB type as
comparison key
}}}

On 6.1 the query succeeds, but with the wrong result.
--
Ticket URL: <https://code.djangoproject.com/ticket/37404#comment:1>

Django

unread,
7:13 AM (16 hours ago) 7:13 AM
to django-...@googlegroups.com
#37404: JSONIn with Value(None, JSONField()) does not match JSON null on Oracle
-------------------------------------+-------------------------------------
Reporter: Clifford Gama | Owner: Clifford
| Gama
Type: Bug | Status: assigned
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: json, oracle, null, | Triage Stage: Accepted
JSONIn |
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Clifford Gama):

* has_patch: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/37404#comment:2>

Django

unread,
7:25 AM (16 hours ago) 7:25 AM
to django-...@googlegroups.com
#37404: JSONIn with Value(None, JSONField()) does not match JSON null on Oracle
-------------------------------------+-------------------------------------
Reporter: Clifford Gama | Owner: Clifford
| Gama
Type: Bug | Status: assigned
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: json, oracle, null, | Triage Stage: Accepted
JSONIn |
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Clifford Gama):

A note on scope: `JSONNull()` and `Value(None, JSONField())` //aren't
expected to be fully equivalent//. `JSONNull()` was added in #35381
because the older spelling couldn't reliably mean JSON `null`, and #36445
(`Value(None, JSONField())` saving SQL `NULL` in `bulk_update()`) was
closed as wontfix on that basis.

This change only widens the existing `JSONNull()` check in
`JSONIn.as_oracle()` to cover a JSON-typed `Value(None)`. `Value(None,
JSONField())` already matches JSON `null` with `__exact` on Oracle, and
with `__in` on the other backends, so Oracle's `__in` is the one place the
lookup disagrees with itself.

That said, since only `JSONNull()` is documented as of 6.1 and
`Value(None, JSONField())` is no longer doc'd, I'd understand closing this
on the same grounds as #36445 if we'd rather not add more handling for the
old spelling.
--
Ticket URL: <https://code.djangoproject.com/ticket/37404#comment:3>

Django

unread,
10:23 AM (13 hours ago) 10:23 AM
to django-...@googlegroups.com
#37404: JSONIn with Value(None, JSONField()) does not match JSON null on Oracle
-------------------------------------+-------------------------------------
Reporter: Clifford Gama | Owner: Clifford
| Gama
Type: Bug | Status: closed
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution: wontfix
Keywords: json, oracle, null, | Triage Stage: Accepted
JSONIn |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* has_patch: 1 => 0
* resolution: => wontfix
* status: assigned => closed

Comment:

Oh good call, a wontfix is more consistent with #36445. I think the
related PR where we were going to reference this ticket to bless a skip
for Oracle ended up chopping said test anyway.
--
Ticket URL: <https://code.djangoproject.com/ticket/37404#comment:4>
Reply all
Reply to author
Forward
0 new messages