mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-03 07:58:59 -04:00
Change how merge_jsonlike treats lists
Current behaviour is to check item-against-item
and merge based on whether items match, irrelevant
of position. This doesn't produce the results we
need for our usecases (merging data to send to
GOVUK Frontend components).
We actually want:
- items to be compared based on their position
- new primitive items at the same position to
overwrite existing ones
- dicts or lists at the same position to be merged
For example,
Starting with this list:
[{"name": "option-1", "value": "1"}]
Merging in this list:
[{"hint": {"text": "Choose one option"}}]
You currently get this:
[
{"name": "option-1", "value": "1"},
{"hint": {"text": "Choose one option"}}
]
We want to get this:
[
{
"name": "option-1", "value": "1",
"hint": {"text": "Choose one option"}
}
]
This commit is contained in:
@@ -651,8 +651,13 @@ def merge_jsonlike(source, destination):
|
||||
return True
|
||||
|
||||
def merge_lists(source, destination):
|
||||
for item in destination:
|
||||
if item not in source:
|
||||
last_dest_idx = len(destination) - 1
|
||||
for idx, item in enumerate(destination):
|
||||
if idx <= last_dest_idx:
|
||||
# assign destination value if can't be merged into source
|
||||
if merge_items(source[idx], destination[idx]) is False:
|
||||
source[idx] = destination[idx]
|
||||
else:
|
||||
source.append(item)
|
||||
|
||||
def merge_dicts(source, destination):
|
||||
|
||||
@@ -614,18 +614,20 @@ def test_get_sample_template_returns_template(template_type):
|
||||
({"a": "b"}, {"c": "d"}, {"a": "b", "c": "d"}),
|
||||
# dicts with nested dict, both under same key, additive behaviour:
|
||||
({"a": {"b": "c"}}, {"a": {"e": "f"}}, {"a": {"b": "c", "e": "f"}}),
|
||||
# same key in both dicts, value is a string, destination supersedes source:
|
||||
# same key in both dicts, value is a string, destination supercedes source:
|
||||
({"a": "b"}, {"a": "c"}, {"a": "c"}),
|
||||
# lists with same length but different items, destination supercedes source:
|
||||
(["b", "c", "d"], ["b", "e", "f"], ["b", "e", "f"]),
|
||||
# lists in dicts behave as top level lists
|
||||
({"a": ["b", "c", "d"]}, {"a": ["b", "e", "f"]}, {"a": ["b", "c", "d", "e", "f"]}),
|
||||
# lists with same string in both result in a list of unique values
|
||||
(["a", "b", "c", "d"], ["d", "e", "f"], ["a", "b", "c", "d", "e", "f"]),
|
||||
({"a": ["b", "c", "d"]}, {"a": ["b", "e", "f"]}, {"a": ["b", "e", "f"]}),
|
||||
# lists with same string in both, at different positions, result in duplicates keeping their positions
|
||||
(["a", "b", "c", "d"], ["d", "e", "f"], ["d", "e", "f", "d"]),
|
||||
# lists with same dict in both result in a list with one instance of that dict
|
||||
([{"b": "c"}], [{"b": "c"}], [{"b": "c"}]),
|
||||
# if dicts in lists have different values, they are not merged
|
||||
([{"b": "c"}], [{"b": "e"}], [{"b": "c"}, {"b": "e"}]),
|
||||
([{"b": "c"}], [{"b": "e"}], [{"b": "e"}]),
|
||||
# merge a dict with a null object returns that dict (does not work the other way round)
|
||||
({"a": {"b": "c"}}, None, {"a": {"b": "c"}}),
|
||||
({"a": {"b": "c"}}, None, {"a": {"b": "c"}})
|
||||
])
|
||||
def test_merge_jsonlike_merges_jsonlike_objects_correctly(source_object, destination_object, expected_result):
|
||||
merge_jsonlike(source_object, destination_object)
|
||||
|
||||
Reference in New Issue
Block a user