diff --git a/airflow/www/views.py b/airflow/www/views.py
index d6bc40b882b01..750cbd9ef4591 100644
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -3518,19 +3518,17 @@ def process_form(self, form, is_created):
"""Process form data."""
conn_type = form.data['conn_type']
conn_id = form.data["conn_id"]
- extra = {
- key: form.data[key]
- for key in self.extra_fields
- if key in form.data and key.startswith(f"extra__{conn_type}__")
- }
- # If parameters are added to the classic `Extra` field, include these values along with
- # custom-field extras.
- extra_conn_params = form.data.get("extra")
+ # The extra value is the combination of custom fields for this conn_type and the Extra field.
+ # The extra form field with all extra values (including custom fields) is in the form being processed
+ # so we start with those values, and override them with anything in the custom fields.
+ extra = {}
+
+ extra_field = form.data.get("extra")
- if extra_conn_params:
+ if extra_field:
try:
- extra.update(json.loads(extra_conn_params))
+ extra.update(json.loads(extra_field))
except (JSONDecodeError, TypeError):
flash(
Markup(
@@ -3539,11 +3537,19 @@ def process_form(self, form, is_created):
"
If connection parameters need to be added to Extra, "
"please make sure they are in the form of a single, valid JSON object.
"
"The following Extra parameters were not added to the connection:
"
- f"{extra_conn_params}",
+ f"{extra_field}",
),
category="error",
)
+ custom_fields = {
+ key: form.data[key]
+ for key in self.extra_fields
+ if key in form.data and key.startswith(f"extra__{conn_type}__")
+ }
+
+ extra.update(custom_fields)
+
if extra.keys():
form.extra.data = json.dumps(extra)
diff --git a/tests/www/views/test_views_connection.py b/tests/www/views/test_views_connection.py
index 249bf2a28e8f8..d64d2615de59d 100644
--- a/tests/www/views/test_views_connection.py
+++ b/tests/www/views/test_views_connection.py
@@ -107,6 +107,21 @@ def test_process_form_extras():
assert json.loads(mock_form.extra.data) == {"extra__test3__custom_field": "custom_field_val3"}
+ # Testing parameters set in both extra and custom fields (cunnection updates).
+ mock_form = mock.Mock()
+ mock_form.data = {
+ "conn_type": "test4",
+ "conn_id": "extras_test4",
+ "extra": '{"extra__test4__custom_field": "custom_field_val3"}',
+ "extra__test4__custom_field": "custom_field_val4",
+ }
+
+ cmv = ConnectionModelView()
+ cmv.extra_fields = ["extra__test4__custom_field"] # Custom field
+ cmv.process_form(form=mock_form, is_created=True)
+
+ assert json.loads(mock_form.extra.data) == {"extra__test4__custom_field": "custom_field_val4"}
+
def test_duplicate_connection(admin_client):
"""Test Duplicate multiple connection with suffix"""