Попытка объединить два json с помощью словаря python

Я пытаюсь объединить два json, хранящихся в словарях python. Здесь первый словарь является родителем, в который вливается второй словарь. На самом деле второй словарь представляет собой вторую строку в файле TSV, содержащую следующую запись массива json. Моя программа пытается прочитать файл TSV построчно и объединить их в один вложенный json. Рассмотрим два словаря: Родительский словарь dict1: {"CA": [{"Marin": [{"zip":1}], "population":10000}]} и, dict2: {"CA": {"Marin": {"zip":2}}}

Примечание: dict1 является источником правды в отношении правильной структуры json.

Здесь, как видите, я хотел бы добавить zip: 2 к округу Марин штата Калифорния.

Вот мой код слияния:

class MyClass:
    # merges two lines containing json arrays inside nested json
    def merge_lines(dict1: dict, dict2: dict) -> dict:
      for key in dict1:
        if key in dict2:
            if isinstance(dict1[key], dict):
                MyClass.merge_lines(dict1[key], dict2[key])
            elif isinstance(dict1[key], list):
                to_be_merged_list = [dict2[key]]
                dict1[key].extend(to_be_merged_list)
      return dict1

Ниже показано, как я пытаюсь проверить:

def test_nested_json_arrays(self):
   d1 = {"CA": [{"Marin": [{"zip":1}], "population":10000}]}
   d2 = {"CA": {"Marin": {"zip":2}}}
   expected_result = {"CA": [{"Marin": [{"zip":1}, {"zip":2}], "population":1000}]}
   actual = MyClass.merge_lines(d1, d2)
   assert expected_result == actual

Однако я получаю следующий результат:

E      AssertionError: assert {'CA': [{'Mar...tion': 1000}]} == {'CA': [{'Mari... {'zip': 2}}]}
E        Differing items:
E        {'CA': [{'Marin': [{'zip': 1}, {'zip': 2}], 'population': 1000}]} != {'CA': [{'Marin': [{'zip': 1}], 'population': 10000}, {'Marin': {'zip': 2}}]}
E        Full diff:
E        - {'CA': [{'Marin': [{'zip': 1}, {'zip': 2}], 'population': 1000}]}
E        + {'CA': [{'Marin': [{'zip': 1}], 'population': 10000}, {'Marin': {'zip': 2}}]}

Может ли кто-нибудь помочь мне выяснить изменения, необходимые в коде, чтобы исправить это? Примечание: имена полей не являются постоянными, и это может применяться к любой комбинации страны, штата, округа, почтового индекса и других вложенных атрибутов.

Что не так с "результатом ниже"? Какой результат вы хотели?

Scott Hunter 18.11.2022 21:53

Я хочу, чтобы это было так: {'CA': [{'Marin': [{'zip': 1}, {'zip': 2}], 'population': 1000}]} .. {'zip':2} должно быть с «Марин».

Aritra Nayak 18.11.2022 21:57
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
2
2
132
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

dict1 = {"CA": [{"Marin": [{"zip":1}], "population":10000}]}
dict2 = {"CA": {"Marin": {"zip":2}}}

Глядя на dict2:

  • Вам дано dict2, содержащее ключ k (в данном случае k = "CA")
  • dict2[k] сам по себе является словарем, который содержит одну (или более) пару ключ (c = "Marin") - значение (z)
  • z теперь это словарь, который вам небезразличен.

Глядя на dict1:

  • Для каждого элемента county_info в dict1[k] вам нужен тот, у которого есть ключ c.
  • Значение этого ключа (county_info[c]) — это список, к которому вы хотите добавить z

Итак, давайте сделаем это:

def merge_lines(dict1, dict2):
    for k, v in dict2.items():
        for c, z in v.items():
            # Find the element of dict1[k] that has the key c:
            for county_info in dict1[k]:
                if c in county_info:
                    county_info[c].append(z)
                    break

Поскольку функция изменяет dict1 на месте, запуск merge_lines(dict1, dict2) дает нам модифицированный dict1, который выглядит так, как вы ожидаете:

{'CA': [{'Marin': [{'zip': 1}, {'zip': 2}], 'population': 10000}]}
Ответ принят как подходящий

Это более общий подход, при котором d1 обновляется с учетом изменений, содержащихся в d2. Конечно, вы должны предоставить больше примеров обновлений от d2, чтобы увидеть, работает ли мое решение во всех случаях.

#!/usr/bin/env python3

d1 = {"CA": [{"Marin": [{"zip": 1}], "population": 10000}]}
d2 = {"CA": {"Marin": {"zip": 2}}}


# read update data from d2 and append new values to d1
def update(d1, d2):
    for key, value in d2.items():
        if key in d1:
            for key1, value1 in value.items():
                if key1 in d1[key][0]:
                    d1[key][0][key1].append(value1)
                else:
                    d1[key][0][key1] = [value1]
        else:
            d1[key] = [value]

    return d1


print(update(d1, d2))

Другие вопросы по теме