Opened 4 months ago
Last modified 7 days ago
#36508 assigned Bug
Asymmetry between exact and iexact when filtering JSON keys against None
| Reported by: | Jacob Walls | Owned by: | Clifford Gama |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 5.2 |
| Severity: | Normal | Keywords: | null, jsonfield |
| Cc: | Sage Abdullah | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
exact and iexact vary in their treatment of None when looking up JSON key paths:
optional_param = request.GET.get("param", None)
qs1 = Model.objects.filter(json__key=optional_param)
qs2 = Model.objects.filter(json__key__iexact=optional_param)
fiddle showing exact queries return rows where the json key is null, but iexact queries do not (instead, they check for key existence, e.g. __key__isnull)
Previous ticket regarding symmetry between exact and iexact: #21552
Previous ticket regarding iexact on JSON key lookups: #27693
Change History (13)
comment:1 by , 4 months ago
| Description: | modified (diff) |
|---|
comment:2 by , 4 months ago
comment:3 by , 4 months ago
| Resolution: | → duplicate |
|---|---|
| Status: | new → closed |
comment:4 by , 4 months ago
Sounds right. Catching up with the comments on #35381 I see that the plan is to change the behavior of json__key=None to match json__key__isnull=True, so that should bring exact into alignment with iexact which already does this. Thanks all!
comment:5 by , 2 months ago
| Cc: | added |
|---|---|
| Resolution: | duplicate |
| Status: | closed → new |
With the discussion in #35381, I think this is a separate issue. The main reason behind adding a JSONNull() that resulted in the creation of that ticket is for addressing the ambiguity of top-level values. Even if #35381 also adds support for using json__key=JSONNull() (at least in the querying case), it's clear that we do want to keep json__key=None to match JSON null in both querying and storing cases.
If #35381 is addressed, I imagine the code that handles None in JSONExact will be replaced with a JSONNull check. Then, the can_use_none_as_rhs probably needs to be moved from JSONExact to KeyTransformExact.
However, it's likely KeyTransformIExact will need the same treatment, as it currently only extends CaseInsensitiveMixin, KeyTransformTextLookupMixin, lookups.IExact without additional code. We might need to refactor KeyTransformExact so that some of its code can be reused by KeyTransformIExact. From a quick guess, these changes seem isolated to #35381.
comment:6 by , 2 months ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:7 by , 2 months ago
A note that this ticket should be specifically for key transform lookups __key__iexact and __key__exact=None, not on the top-level, as the latter will be solved by #35381.
Edit: Apologies, I see Sage already mentions that.
comment:8 by , 2 months ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:9 by , 2 months ago
If I understand correctly, the plan is:
- Deprecate
json__key__iexact=None(currently meaning__json__key__isnull=True), and point users to use__isnull=Trueinstead. - After the deprecation period, change
__json__key__iexact=Noneto match JSON null.
comment:10 by , 2 months ago
We might want to just fix without a deprecation(*), since there is no "upgrade path". If we warn about this, and you discover you really wanted the "new" behavior all along, the only answer would be to just wait, which isn't great.
(*) but doc it as a minor incompatible change?
I feel like most who have gone to the trouble to specify iexact wouldn't expect iexact to simply check key existence, and thus will want the "new" behavior.
comment:11 by , 2 months ago
| Has patch: | set |
|---|
comment:12 by , 5 weeks ago
| Patch needs improvement: | set |
|---|
comment:13 by , 7 days ago
| Patch needs improvement: | unset |
|---|
I feel like this falls into the same bucket, or at least very close, to the other issues relating to trying to do the right thing when
Noneis provided toJSONFieldand that the solution lies in makingNonealways translate toNULLand requireJSONNullin cases where JSONnullis required.