简体   繁体   中英

How do I format JSON's with multiple of the same keys with python?

I have a program that right now grabs data like temperature and loads using a powershell script and the WMI. It outputs the data as a JSON file. Now let me preface this by saying this is my first time every working with JSON's and im not very familiar with the JSON python library. Here is the code to my program:

import subprocess
import json

p = subprocess.Popen(["C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", ". \"./TestScript\";", "&NSV"], stdout=subprocess.PIPE)
(output, err) = p.communicate()

data = json.loads(output)

for mNull in data:
    del mNull['Scope']
    del mNull['Path']
    del mNull['Options']
    del mNull['ClassPath']
    del mNull['Properties']
    del mNull['SystemProperties']
    del mNull['Qualifiers']
    del mNull['Site']
    del mNull['Container']
    del mNull['PSComputerName']
    del mNull['__GENUS']
    del mNull['__CLASS']
    del mNull['__SUPERCLASS']
    del mNull['__DYNASTY']
    del mNull['__RELPATH']
    del mNull['__PROPERTY_COUNT']
    del mNull['__DERIVATION']
    del mNull['__SERVER']
    del mNull['__NAMESPACE']
    del mNull['__PATH']

fdata = json.dumps(data,indent=2)

print(fdata)

Now here is the resulting JSON:

[
  {
    "Name": "Memory",
    "SensorType": "Load",
    "Value": 53.3276978
  },
  {
    "Name": "CPU Core #2",
    "SensorType": "Temperature",
    "Value": 69
  },
  {
    "Name": "Used Space",
    "SensorType": "Load",
    "Value": 93.12801
  },
  {
    "Name": "CPU Core #1",
    "SensorType": "Temperature",
    "Value": 66
  },
  {
    "Name": "CPU DRAM",
    "SensorType": "Power",
    "Value": 1.05141532
  },
  {
    "Name": "CPU Core #2",
    "SensorType": "Load",
    "Value": 60.15625
  },
  {
    "Name": "CPU Package",
    "SensorType": "Power",
    "Value": 15.2162886
  },
  {
    "Name": "Bus Speed",
    "SensorType": "Clock",
    "Value": 100.000031
  },
  {
    "Name": "CPU Total",
    "SensorType": "Load",
    "Value": 57.421875
  },
  {
    "Name": "CPU Package",
    "SensorType": "Temperature",
    "Value": 69
  },
  {
    "Name": "CPU Core #2",
    "SensorType": "Clock",
    "Value": 2700.00073
  },
  {
    "Name": "Temperature",
    "SensorType": "Temperature",
    "Value": 41
  },
  {
    "Name": "Used Memory",
    "SensorType": "Data",
    "Value": 4.215393
  },
  {
    "Name": "Available Memory",
    "SensorType": "Data",
    "Value": 3.68930435
  },
  {
    "Name": "CPU Core #1",
    "SensorType": "Clock",
    "Value": 3100.001
  },
  {
    "Name": "CPU Cores",
    "SensorType": "Power",
    "Value": 13.3746643
  },
  {
    "Name": "CPU Graphics",
    "SensorType": "Power",
    "Value": 0.119861834
  },
  {
    "Name": "CPU Core #1",
    "SensorType": "Load",
    "Value": 54.6875
  }
]

As you can see every dictionary in the list has the keys Name , SensorType and Value .

What I want to do is make it so that each list has a "label" equal to the Name in each one, so I can call for data from specific entries, one at a time. Once again, I'm kind of a newbie with JSON and its library so I'm not even sure if this sort of thing is possible. Any help would be greatly appreciated! Have a good day! :)

Edit 1: Here is an example, using the first 2, of what I would like the program to be able to output.

[
  "Memory":{
    "SensorType": "Load",
    "Value": 53.3276978
  },
  "CPU Core #2":{
    "SensorType": "Temperature",
    "Value": 69
  }
]

Once again, I dont even know if this is valid JSON but I want it to just do something at least similar to that so I can call, for example, print(data["Memory"]["Value"]) and return, 53.3276978 .

Edit 2: It did just occur to me that there are some names with multiple sensor types, for example, "CPU Core #1" and "CPU Core #2" both have "Tempurature" , "Load" , and "Clock" . Using the above example could cause some conflicts so is there a way we could account for that?

Assuming you need to keep the values if key already exists:

import json
data = [
{
    "Name": "Memory",
    "SensorType": "Load",
    "Value": 53.3276978
},
{
    "Name": "CPU Core #2",
    "SensorType": "Temperature",
    "Value": 69
},
{
    "Name": "Used Space",
    "SensorType": "Load",
    "Value": 93.12801
},
{
    "Name": "CPU Core #1",
    "SensorType": "Temperature",
    "Value": 66
},
{
    "Name": "CPU DRAM",
    "SensorType": "Power",
    "Value": 1.05141532
},
{
    "Name": "CPU Core #2",
    "SensorType": "Load",
    "Value": 60.15625
},
{
    "Name": "CPU Package",
    "SensorType": "Power",
    "Value": 15.2162886
},
{
    "Name": "Bus Speed",
    "SensorType": "Clock",
    "Value": 100.000031
},
{
    "Name": "CPU Total",
    "SensorType": "Load",
    "Value": 57.421875
},
{
    "Name": "CPU Package",
    "SensorType": "Temperature",
    "Value": 69
},
{
    "Name": "CPU Core #2",
    "SensorType": "Clock",
    "Value": 2700.00073
},
{
    "Name": "Temperature",
    "SensorType": "Temperature",
    "Value": 41
},
{
    "Name": "Used Memory",
    "SensorType": "Data",
    "Value": 4.215393
},
{
    "Name": "Available Memory",
    "SensorType": "Data",
    "Value": 3.68930435
},
{
    "Name": "CPU Core #1",
    "SensorType": "Clock",
    "Value": 3100.001
},
{
    "Name": "CPU Cores",
    "SensorType": "Power",
    "Value": 13.3746643
},
{
    "Name": "CPU Graphics",
    "SensorType": "Power",
    "Value": 0.119861834
},
{
    "Name": "CPU Core #1",
    "SensorType": "Load",
    "Value": 54.6875
}
]

final_data = {}

for d in data:
    if d['Name'] not in final_data:
        final_data[d['Name']] = list()

    key = d.pop('Name')
    final_data[key].append(temp)


print json.dumps(final_data,indent=4)

will give you

{
"CPU Package": [
    {
        "SensorType": "Power",
        "Value": 15.2162886
    },
    {
        "SensorType": "Temperature",
        "Value": 69
    }
],
"Temperature": [
    {
        "SensorType": "Temperature",
        "Value": 41
    }
],
"CPU Core #2": [
    {
        "SensorType": "Temperature",
        "Value": 69
    },
    {
        "SensorType": "Load",
        "Value": 60.15625
    },
    {
        "SensorType": "Clock",
        "Value": 2700.00073
    }
],
"CPU Core #1": [
    {
        "SensorType": "Temperature",
        "Value": 66
    },
    {
        "SensorType": "Clock",
        "Value": 3100.001
    },
    {
        "SensorType": "Load",
        "Value": 54.6875
    }
],
"CPU Cores": [
    {
        "SensorType": "Power",
        "Value": 13.3746643
    }
],
"Available Memory": [
    {
        "SensorType": "Data",
        "Value": 3.68930435
    }
],
"Used Space": [
    {
        "SensorType": "Load",
        "Value": 93.12801
    }
],
"Bus Speed": [
    {
        "SensorType": "Clock",
        "Value": 100.000031
    }
],
"Memory": [
    {
        "SensorType": "Load",
        "Value": 53.3276978
    }
],
"Used Memory": [
    {
        "SensorType": "Data",
        "Value": 4.215393
    }
],
"CPU Total": [
    {
        "SensorType": "Load",
        "Value": 57.421875
    }
],
"CPU DRAM": [
    {
        "SensorType": "Power",
        "Value": 1.05141532
    }
],
"CPU Graphics": [
    {
        "SensorType": "Power",
        "Value": 0.119861834
    }
]
}

Hope this helps

You can build a new dictionary in the shape you want like this:

...
data = {
    element["Name"]: {
        key: value for key, value in element.items() if key != "Name"
    }
    for element in json.loads(output)
}
fdata = json.dumps(data, indent=4)
...

Result:

{
    "Memory": {
        "SensorType": "Load",
        "Value": 53.3276978
    },
    "CPU Core #2": {
        "SensorType": "Clock",
        "Value": 2700.00073
    },
    (and so on)
}
x="""[
  {
    "Name": "Memory 1",
    "SensorType": "Load",
    "Value": 53.3276978
  },
  {
    "Name": "CPU Core #2",
    "SensorType": "Load",
    "Value": 53.3276978
  }]"""

json_obj=json.loads(x)

new_list=[]
for item in json_obj:
    name=item.pop('Name')
    new_list.append({name:item})

print(json.dumps(new_list,indent=4))

Output

[
{
    "Memory 1": {
        "SensorType": "Load", 
        "Value": 53.3276978
    }
}, 
{
    "CPU Core #2": {
        "SensorType": "Load", 
        "Value": 53.3276978
    }
}
]

How about this?

import json
orig_list = json.load(<filename>)
new_dict = { l['Name']:{k:v for k,v in l.items() if k!='Name'} for l in orig_list}
json.dumps(new_dict, <filename>)

This way, you won't have to del items from the dict s that you load from the file.

You can just replace

for mNull in data:
    del mNull['Scope']
    del mNull['Path']
    del mNull['Options']
    del mNull['ClassPath']
    del mNull['Properties']
    del mNull['SystemProperties']
    del mNull['Qualifiers']
    del mNull['Site']
    del mNull['Container']
    del mNull['PSComputerName']
    del mNull['__GENUS']
    del mNull['__CLASS']
    del mNull['__SUPERCLASS']
    del mNull['__DYNASTY']
    del mNull['__RELPATH']
    del mNull['__PROPERTY_COUNT']
    del mNull['__DERIVATION']
    del mNull['__SERVER']
    del mNull['__NAMESPACE']
    del mNull['__PATH']

fdata = json.dumps(data,indent=2)

with

dontwant=set(['Name', 'PSComputerName', '__RELPATH', '__DYNASTY', '__CLASS', '__PROPERTY_COUNT', 'Site', 'ClassPath', 'SystemProperties', 'Scope', 'Qualifiers', 'Options', '__NAMESPACE', 'Path', '__SUPERCLASS', '__DERIVATION', '__GENUS', '__PATH', 'Container', 'Properties', '__SERVER']) # set of keys to drop
out={} # empty dict
for mNull in data:
    name=mNull['Name']
    out[name]={key:value for key,value in mNull.items() if key not in dontwant} # only copy over items you want

fdata = json.dumps(out,indent=2)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM