This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new ca73694702 refactor: Added get_extra_dejson method with nested 
parameter which allows you to specify if you want the nested json as string to 
be also deserialized.  The extra_dejson property uses this method with nested 
set to False. (#39811)
ca73694702 is described below

commit ca73694702cc389b4ffb8486a303eec0788470b4
Author: David Blain <[email protected]>
AuthorDate: Fri Jun 14 19:24:21 2024 +0200

    refactor: Added get_extra_dejson method with nested parameter which allows 
you to specify if you want the nested json as string to be also deserialized.  
The extra_dejson property uses this method with nested set to False. (#39811)
    
    Co-authored-by: David Blain <[email protected]>
---
 airflow/models/connection.py    | 32 ++++++++++++++++++++++++--------
 tests/models/test_connection.py | 23 +++++++++++++++++++++++
 2 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/airflow/models/connection.py b/airflow/models/connection.py
index 6e1435ebfa..95855e15fe 100644
--- a/airflow/models/connection.py
+++ b/airflow/models/connection.py
@@ -20,6 +20,7 @@ from __future__ import annotations
 import json
 import logging
 import warnings
+from contextlib import suppress
 from json import JSONDecodeError
 from typing import Any
 from urllib.parse import parse_qsl, quote, unquote, urlencode, urlsplit
@@ -471,21 +472,36 @@ class Connection(Base, LoggingMixin):
 
         return status, message
 
-    @property
-    def extra_dejson(self) -> dict:
-        """Returns the extra property by deserializing json."""
-        obj = {}
+    def get_extra_dejson(self, nested: bool = False) -> dict:
+        """
+        Deserialize extra property to JSON.
+
+        :param nested: Determines whether nested structures are also 
deserialized into JSON (default False).
+        """
+        extra = {}
+
         if self.extra:
             try:
-                obj = json.loads(self.extra)
-
+                if nested:
+                    for key, value in json.loads(self.extra).items():
+                        extra[key] = value
+                        if isinstance(value, str):
+                            with suppress(JSONDecodeError):
+                                extra[key] = json.loads(value)
+                else:
+                    extra = json.loads(self.extra)
             except JSONDecodeError:
                 self.log.exception("Failed parsing the json for conn_id %s", 
self.conn_id)
 
             # Mask sensitive keys from this list
-            mask_secret(obj)
+            mask_secret(extra)
+
+        return extra
 
-        return obj
+    @property
+    def extra_dejson(self) -> dict:
+        """Returns the extra property by deserializing json."""
+        return self.get_extra_dejson()
 
     @classmethod
     def get_connection_from_secrets(cls, conn_id: str) -> Connection:
diff --git a/tests/models/test_connection.py b/tests/models/test_connection.py
index 21e5682c8d..3f7504713f 100644
--- a/tests/models/test_connection.py
+++ b/tests/models/test_connection.py
@@ -250,3 +250,26 @@ class TestConnection:
     # string works as expected.
     def test_sanitize_conn_id(self, connection, expected_conn_id):
         assert connection.conn_id == expected_conn_id
+
+    def test_extra_dejson(self):
+        extra = (
+            '{"trust_env": false, "verify": false, "stream": true, "headers":'
+            '{\r\n "Content-Type": "application/json",\r\n  "X-Requested-By": 
"Airflow"\r\n}}'
+        )
+        connection = Connection(
+            conn_id="pokeapi",
+            conn_type="http",
+            login="user",
+            password="pass",
+            host="https://pokeapi.co/";,
+            port=100,
+            schema="https",
+            extra=extra,
+        )
+
+        assert connection.extra_dejson == {
+            "trust_env": False,
+            "verify": False,
+            "stream": True,
+            "headers": {"Content-Type": "application/json", "X-Requested-By": 
"Airflow"},
+        }

Reply via email to