How to compare 2 json files and merge in one with python

83 Views Asked by At

Im trying to compare if a value from jsonA(deployed_devices) exists in jsonB(assigned_components) and merge them into one new json Object. The goal is to iterate over every asset_it in the deployed_devices json and check if and where the asset_id matches witch the id in assigned_components[data][rows] and generate a new JSON. Heres my current code which generates a new json but leaves the 'Components' in the new JSON(matched_devices) completely empty:

def match_device_components(assigned_components, deployed_devices):
    matched_devices = []

    for component_entry in assigned_components:
        for component_name, component_data in component_entry.items():
            component_rows = component_data.get('data', {}).get('rows', [])

            assigned_component_ids = {component["id"] for component in component_rows}

            for device in deployed_devices:
                matched_components = []

                for component in component_rows:
                    if component["id"] == device["asset_id"]:
                        matched_components.append(component["name"])

                matched_device = {
                    "model_name": device["model_name"],
                    "asset_tag": device["asset_tag"],
                    "asset_id": device["asset_id"],
                    "components": matched_components
                }

                matched_devices.append(matched_device)

    return matched_devices

Those are the JSON to work with (cropped the output a bit for better overview):

deployed_devices = [
    {
        "model_name": "RACK/BOX",
        "asset_tag": "X-0043",
        "asset_id": "234"
    },
    .... more devices ... 
]

assigned_components = [
   {
      "Camera":{
         "id":70,
         "name":"Camera",
         "user_can_checkout":1,
         "available_actions":{
            "checkout":true,
            "checkin":true,
            "update":true,
            "delete":true
         }
      },
      "data":{
         "total":52,
         "rows":[
            {
               "assigned_pivot_id":710,
               "id":133,
               "name":"BOX 25x17x21",
               "qty":2,
               "note":"",
               "type":"asset",
               "created_at":{
                  "datetime":"2024-01-15 11:59:06",
                  "formatted":"15.01.2024 11:59"
               },
               "available_actions":{
                  "checkin":true
               }
            },
            ... many more rows ... 
         ]
      }
   },
   {
      "LED":{
         "id":69,
         "name":"LED ",
         "user_can_checkout":1,
         "available_actions":{
            "checkout":true,
            "checkin":true,
            "update":true,
            "delete":true
         }
      },
      "data":{
         "total":10,
         "rows":[
            {
               "assigned_pivot_id":823,
               "id":57,
               "name":"BOX 25x17x21",
               "qty":1,
               "note":"None",
               "type":"asset",
               "created_at":{
                  "datetime":"2024-01-22 10:50:34",
                  "formatted":"22.01.2024 10:50"
               },
               "available_actions":{
                  "checkin":true
               }
            },
            ... many more rows ... 
         ]
      }
   }
]
2

There are 2 best solutions below

5
CikoXp On

Ok let's solve this issue:

  1. You code is a bit confused because your for loops actually doesn't give any result, so I advise you to 'print' your variables to understand what are you doing;
  2. You are talking about JSON format so the better way to manage JSON database is to use dedicated python package;
  3. Your question is a bit unclear.

Having said that, here's the solution:

def match_device_components(assigned_components, deployed_devices):
   matched_devices = []
   matched_components = []

   for components in json.loads(json.dumps(assigned_components)):
       c_id=components['data']['rows'][0]['id']
       # print(c_id)

   for device in json.loads(json.dumps(deployed_devices)):
       d_id=device['asset_id']
       # print(d_id)

   if int(c_id) == int(d_id):
       matched_components.append(components['data']['rows'][0]['name'])

       matched_device = {
           "model_name": device["model_name"],
           "asset_tag": device["asset_tag"],
           "asset_id": device["asset_id"],
           "components": matched_components
       }

       matched_devices.append(matched_device)  
       print(json.dumps(matched_device, indent=4))

if __name__ == '__main__':
   match_device_components(assigned_components, deployed_devices)

This function will make this variable. I hope this is your goal.

{
    "model_name": "RACK/BOX",
    "asset_tag": "X-0043",
    "asset_id": "57",
    "components": [
        "BOX 25x17x21"
    ]
}

EDIT

Ok, keep in mind this: Since I do not know how your JSON files are made and from where they come from, to give you a working solution I had to "invent" a code to simulate your application. So in my answer I simply wrote the working function because my .py as it is doesn't make sense in your environment. But due to your doubts, here's my full working code, please copy/paste it in a new .py file and launch it with python3:

import json

deployed_devices = [
    {
        "model_name": "RACK/BOX",
        "asset_tag": "X-0043",
        "asset_id": "57"
    }
]

assigned_components = [
   {
      "Camera":{
         "id":70,
         "name":"Camera",
         "user_can_checkout":1,
         "available_actions":{
            "checkout":True,
            "checkin":True,
            "update":True,
            "delete":True
         }
      },
      "data":{
         "total":52,
         "rows":[
            {
               "assigned_pivot_id":710,
               "id":133,
               "name":"BOX 25x17x21",
               "qty":2,
               "note":"",
               "type":"asset",
               "created_at":{
                  "datetime":"2024-01-15 11:59:06",
                  "formatted":"15.01.2024 11:59"
               },
               "available_actions":{
                  "checkin":True
               }
            }
         ]
      }
   },
   {
      "LED":{
         "id":69,
         "name":"LED ",
         "user_can_checkout":1,
         "available_actions":{
            "checkout":True,
            "checkin":True,
            "update":True,
            "delete":True
         }
      },
      "data":{
         "total":10,
         "rows":[
            {
               "assigned_pivot_id":823,
               "id":57,
               "name":"BOX 25x17x21",
               "qty":1,
               "note":"None",
               "type":"asset",
               "created_at":{
                  "datetime":"2024-01-22 10:50:34",
                  "formatted":"22.01.2024 10:50"
               },
               "available_actions":{
                  "checkin":True
               }
            }
         ]
      }
   }
]

def match_device_components(assigned_components, deployed_devices):
    matched_devices = []
    matched_components = []

    for components in json.loads(json.dumps(assigned_components)):
        c_id=components['data']['rows'][0]['id']

    for device in json.loads(json.dumps(deployed_devices)):
        d_id=device['asset_id']

    if int(c_id) == int(d_id):
        matched_components.append(components['data']['rows'][0]['name'])

        matched_device = {
            "model_name": device["model_name"],
            "asset_tag": device["asset_tag"],
            "asset_id": device["asset_id"],
            "components": matched_components
        }

        matched_devices.append(matched_device)  
        print(json.dumps(matched_device, indent=4))

if __name__ == '__main__':
    match_device_components(assigned_components, deployed_devices)

NB: I've edited all "true" keyword with "True" to avoid errors in VSCode since "true" does not exists in python3. So do not consider at all them. Are totally useless in this case.

You will have this result: (So my code works good. It's up to you make it work in your environment!)

VSCode result

0
Nico On

I managed to get it working with the following code:

def match_device_components(assigned_components, deployed_devices):
    result = []
    for device in deployed_devices:
        components = []
        for component in assigned_components:
            currentcomponentname = list(component.keys())[0]
            for assigned_device in component['data']['rows']:
                if int(device['asset_id']) == int(assigned_device['id']):
                    components.append(currentcomponentname)
                    break

        result.append({ 
            'asset_id': device['asset_id'],
            'asset_tag': device['asset_tag'],
            'model_name': device['model_name'],
            'components': components
        })

    return result