Browse Source

Refs #33308 -- Removed support for passing encoded JSON string literals to JSONField & co.

Per deprecation timeline.
Mariusz Felisiak 1 year ago
parent
commit
5e4c1793b7

+ 0 - 33
django/contrib/postgres/aggregates/general.py

@@ -1,9 +1,5 @@
-import json
-import warnings
-
 from django.contrib.postgres.fields import ArrayField
 from django.db.models import Aggregate, BooleanField, JSONField, TextField, Value
-from django.utils.deprecation import RemovedInDjango51Warning
 
 from .mixins import OrderableAggMixin
 
@@ -57,35 +53,6 @@ class JSONBAgg(OrderableAggMixin, Aggregate):
     allow_distinct = True
     output_field = JSONField()
 
-    # RemovedInDjango51Warning: When the deprecation ends, remove __init__().
-    def __init__(self, *expressions, default=None, **extra):
-        super().__init__(*expressions, default=default, **extra)
-        if (
-            isinstance(default, Value)
-            and isinstance(default.value, str)
-            and not isinstance(default.output_field, JSONField)
-        ):
-            value = default.value
-            try:
-                decoded = json.loads(value)
-            except json.JSONDecodeError:
-                warnings.warn(
-                    "Passing a Value() with an output_field that isn't a JSONField as "
-                    "JSONBAgg(default) is deprecated. Pass default="
-                    f"Value({value!r}, output_field=JSONField()) instead.",
-                    stacklevel=2,
-                    category=RemovedInDjango51Warning,
-                )
-                self.default.output_field = self.output_field
-            else:
-                self.default = Value(decoded, self.output_field)
-                warnings.warn(
-                    "Passing an encoded JSON string as JSONBAgg(default) is "
-                    f"deprecated. Pass default={decoded!r} instead.",
-                    stacklevel=2,
-                    category=RemovedInDjango51Warning,
-                )
-
 
 class StringAgg(OrderableAggMixin, Aggregate):
     function = "STRING_AGG"

+ 4 - 27
django/db/models/fields/json.py

@@ -1,5 +1,4 @@
 import json
-import warnings
 
 from django import forms
 from django.core import checks, exceptions
@@ -12,7 +11,6 @@ from django.db.models.lookups import (
     PostgresOperatorLookup,
     Transform,
 )
-from django.utils.deprecation import RemovedInDjango51Warning
 from django.utils.translation import gettext_lazy as _
 
 from . import Field
@@ -101,31 +99,10 @@ class JSONField(CheckFieldDefaultMixin, Field):
     def get_db_prep_value(self, value, connection, prepared=False):
         if not prepared:
             value = self.get_prep_value(value)
-        # RemovedInDjango51Warning: When the deprecation ends, replace with:
-        # if (
-        #     isinstance(value, expressions.Value)
-        #     and isinstance(value.output_field, JSONField)
-        # ):
-        #     value = value.value
-        # elif hasattr(value, "as_sql"): ...
-        if isinstance(value, expressions.Value):
-            if isinstance(value.value, str) and not isinstance(
-                value.output_field, JSONField
-            ):
-                try:
-                    value = json.loads(value.value, cls=self.decoder)
-                except json.JSONDecodeError:
-                    value = value.value
-                else:
-                    warnings.warn(
-                        "Providing an encoded JSON string via Value() is deprecated. "
-                        f"Use Value({value!r}, output_field=JSONField()) instead.",
-                        category=RemovedInDjango51Warning,
-                    )
-            elif isinstance(value.output_field, JSONField):
-                value = value.value
-            else:
-                return value
+        if isinstance(value, expressions.Value) and isinstance(
+            value.output_field, JSONField
+        ):
+            value = value.value
         elif hasattr(value, "as_sql"):
             return value
         return connection.ops.adapt_json_value(value, self.encoder)

+ 3 - 0
docs/releases/5.1.txt

@@ -274,3 +274,6 @@ to remove usage of these features.
 * The ``SimpleTestCase.assertFormsetError()`` method is removed.
 
 * The ``TransactionTestCase.assertQuerysetEqual()`` method is removed.
+
+* Support for passing encoded JSON string literals to ``JSONField`` and
+  associated lookups and expressions is removed.

+ 0 - 4
docs/topics/db/queries.txt

@@ -1085,10 +1085,6 @@ Unless you are sure you wish to work with SQL ``NULL`` values, consider setting
     Storing JSON scalar ``null`` does not violate :attr:`null=False
     <django.db.models.Field.null>`.
 
-.. deprecated:: 4.2
-
-    Passing ``Value("null")`` to express JSON ``null`` is deprecated.
-
 .. fieldlookup:: jsonfield.key
 
 Key, index, and path transforms

+ 0 - 25
tests/model_fields/test_jsonfield.py

@@ -37,7 +37,6 @@ from django.db.models.fields.json import (
 from django.db.models.functions import Cast
 from django.test import SimpleTestCase, TestCase, skipIfDBFeature, skipUnlessDBFeature
 from django.test.utils import CaptureQueriesContext
-from django.utils.deprecation import RemovedInDjango51Warning
 
 from .models import CustomJSONDecoder, JSONModel, NullableJSONModel, RelatedJSONModel
 
@@ -216,30 +215,6 @@ class TestSaveLoad(TestCase):
         obj.refresh_from_db()
         self.assertIsNone(obj.value)
 
-    def test_ambiguous_str_value_deprecation(self):
-        msg = (
-            "Providing an encoded JSON string via Value() is deprecated. Use Value([], "
-            "output_field=JSONField()) instead."
-        )
-        with self.assertWarnsMessage(RemovedInDjango51Warning, msg):
-            obj = NullableJSONModel.objects.create(value=Value("[]"))
-        obj.refresh_from_db()
-        self.assertEqual(obj.value, [])
-
-    @skipUnlessDBFeature("supports_primitives_in_json_field")
-    def test_value_str_primitives_deprecation(self):
-        msg = (
-            "Providing an encoded JSON string via Value() is deprecated. Use "
-            "Value(None, output_field=JSONField()) instead."
-        )
-        with self.assertWarnsMessage(RemovedInDjango51Warning, msg):
-            obj = NullableJSONModel.objects.create(value=Value("null"))
-        obj.refresh_from_db()
-        self.assertIsNone(obj.value)
-        obj = NullableJSONModel.objects.create(value=Value("invalid-json"))
-        obj.refresh_from_db()
-        self.assertEqual(obj.value, "invalid-json")
-
     @skipUnlessDBFeature("supports_primitives_in_json_field")
     def test_json_null_different_from_sql_null(self):
         json_null = NullableJSONModel.objects.create(value=Value(None, JSONField()))

+ 1 - 55
tests/postgres_tests/test_aggregates.py

@@ -14,9 +14,8 @@ from django.db.models import (
 from django.db.models.fields.json import KeyTextTransform, KeyTransform
 from django.db.models.functions import Cast, Concat, Substr
 from django.test import skipUnlessDBFeature
-from django.test.utils import Approximate, ignore_warnings
+from django.test.utils import Approximate
 from django.utils import timezone
-from django.utils.deprecation import RemovedInDjango51Warning
 
 from . import PostgreSQLTestCase
 from .models import AggregateTestModel, HotelReservation, Room, StatTestModel
@@ -152,59 +151,6 @@ class TestGeneralAggregate(PostgreSQLTestCase):
                     )
                     self.assertEqual(values, {"aggregation": expected_result})
 
-    @ignore_warnings(category=RemovedInDjango51Warning)
-    def test_jsonb_agg_default_str_value(self):
-        AggregateTestModel.objects.all().delete()
-        queryset = AggregateTestModel.objects.all()
-        self.assertEqual(
-            queryset.aggregate(
-                aggregation=JSONBAgg("integer_field", default=Value("<empty>"))
-            ),
-            {"aggregation": "<empty>"},
-        )
-
-    def test_jsonb_agg_default_str_value_deprecation(self):
-        queryset = AggregateTestModel.objects.all()
-        msg = (
-            "Passing a Value() with an output_field that isn't a JSONField as "
-            "JSONBAgg(default) is deprecated. Pass default=Value('<empty>', "
-            "output_field=JSONField()) instead."
-        )
-        with self.assertWarnsMessage(RemovedInDjango51Warning, msg):
-            queryset.aggregate(
-                aggregation=JSONBAgg("integer_field", default=Value("<empty>"))
-            )
-        with self.assertWarnsMessage(RemovedInDjango51Warning, msg):
-            queryset.none().aggregate(
-                aggregation=JSONBAgg("integer_field", default=Value("<empty>"))
-            ),
-
-    @ignore_warnings(category=RemovedInDjango51Warning)
-    def test_jsonb_agg_default_encoded_json_string(self):
-        AggregateTestModel.objects.all().delete()
-        queryset = AggregateTestModel.objects.all()
-        self.assertEqual(
-            queryset.aggregate(
-                aggregation=JSONBAgg("integer_field", default=Value("[]"))
-            ),
-            {"aggregation": []},
-        )
-
-    def test_jsonb_agg_default_encoded_json_string_deprecation(self):
-        queryset = AggregateTestModel.objects.all()
-        msg = (
-            "Passing an encoded JSON string as JSONBAgg(default) is deprecated. Pass "
-            "default=[] instead."
-        )
-        with self.assertWarnsMessage(RemovedInDjango51Warning, msg):
-            queryset.aggregate(
-                aggregation=JSONBAgg("integer_field", default=Value("[]"))
-            )
-        with self.assertWarnsMessage(RemovedInDjango51Warning, msg):
-            queryset.none().aggregate(
-                aggregation=JSONBAgg("integer_field", default=Value("[]"))
-            )
-
     def test_array_agg_charfield(self):
         values = AggregateTestModel.objects.aggregate(arrayagg=ArrayAgg("char_field"))
         self.assertEqual(values, {"arrayagg": ["Foo1", "Foo2", "Foo4", "Foo3"]})