Selecting fields from JSON output - python

Using Python, how can i extract the field id to a variable? Basicaly, i to transform this:
{
"accountWide": true,
"criteria": [
{
"description": "some description",
"id": 7553,
"max": 1,
"orderIndex": 0
}
]
}
to something like
print "Description is: " + description
print "ID is: " + id
print "Max value is : " + max

Assume you stored that dictionary in a variable called values. To get id in to a variable, do:
idValue = values['criteria'][0]['id']
If that json is in a file, do the following to load it:
import json
jsonFile = open('your_filename.json', 'r')
values = json.load(jsonFile)
jsonFile.close()
If that json is from a URL, do the following to load it:
import urllib, json
f = urllib.urlopen("http://domain/path/jsonPage")
values = json.load(f)
f.close()
To print ALL of the criteria, you could:
for criteria in values['criteria']:
for key, value in criteria.iteritems():
print key, 'is:', value
print ''

Assuming you are dealing with a JSON-string in the input, you can parse it using the json package, see the documentation.
In the specific example you posted you would need
x = json.loads("""{
"accountWide": true,
"criteria": [
{
"description": "some description",
"id": 7553,
"max": 1,
"orderIndex": 0
}
]
}""")
description = x['criteria'][0]['description']
id = x['criteria'][0]['id']
max = x['criteria'][0]['max']

Related

How to get a value of a dictionary within a list of dictionaries when the dict equals a certain name?

I want to retrieve certain values from a list object that contains strings and dictionaries. If the dictionary equals a certain name I want to add it to the output file.
First I read in a json file which looks like this:
{
"event": "user",
"timestamp": {
"$numberDouble": "1671459681.4369426"
},
"metadata": {
"model_id": "125817626"
},
"text": "hello",
"parse_data": {
"intent": {
"name": "greet",
"confidence": {
"$numberDouble": "1.0"
}
},
I have events that equal "user" and those that equal "bot". What I want to have in the end is an output file that has user and bot in each line. At the beginning of the line I also want to have the timestamp, formatted in human readable time, and at the end the text like
2020-03-13 12:11:25 user: hello
2020-03-13 12:11:28 bot: Hi
However, I do not know how to access the value of "timestamp", format it and then print it together with "user" and "text" in one line.
What I have done so far is that:
import json
from datetime import datetime
f = open('1234.json')
data = json.load(f)
all_events = [e for e in data.get('events', list()) if e.get('event')=='user' or e.get('event')=='bot']
file_object = open('1234.txt', 'a')
for event in all_events:
file_object.write(str(event.get('timestamp'))+ " "+ event.get('event')+ ": " + event.get('text', '')+ "\n")
f.close()
What I get with this is:
{'$numberDouble': '1671459681.4369426'} user: hello
I know that I can use something like this to format the time
ts = int("1584101485")
print(datetime.utcfromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S'))
But I do not know how to wrap this in my file_object.write command
Instead of getting the timestamp key's value, you need to parse the $numberDouble value inside of the timestamp dictionary:
file_object.write(
datetime.utcfromtimestamp(float(event['timestamp']['$numberDouble'])).strftime('%Y-%m-%d %H:%M:%S') + " "+ event.get('event')+ ": " + event.get('text', '')+ "\n"
)

Remove fields from a json array in Python

Currently I have a function returning json via jsonify.
[
{
"hostname": "bla",
"ipaddress": "192.168.1.10",
"subnetmask": "255.255.255.0",
"iloip": "192.168.1.11"
}
]
I want to keep it in json format, but I want to only show the fields I choose (i.e. reduce it). For this example, I want hostname and ipaddress.
Thanks
You can use dict comprehension:
json_input = '''
[
{
"hostname": "bla",
"ipaddress": "192.168.1.10",
"subnetmask": "255.255.255.0",
"iloip": "192.168.1.11"
}
]
'''
desired_keys = {'hostname', 'ipaddress'}
json_filtered = json.dumps([{ k:v for (k,v) in d.items() if k in desired_keys}
for d in json.loads(json_input)])
print(json_filtered)
output:
'[{"hostname": "bla", "ipaddress": "192.168.1.10"}]'
I belive what you want to achieve can be done with the code given below:
import json
data_json = '{"hostname": "bla","ipaddress": "192.168.1.10","subnetmask": "255.255.255.0","iloip": "192.168.1.11"}'
data = json.loads(data_json)
chosen_fields = ['hostname', 'ipaddress']
for field in chosen_fields:
print(f'{field}: {data[field]}')
Output:
hostname: bla
ipaddress: 192.168.1.10
Here what we do is we parse the stringified version of the json using the python's json module (i.e. json.loads(...)). Next decide on the fields we want to access (i.e. chosen_fields). Finally we iterate through the field we want to reach and get the corresponding values of the fields. This leaves the original json unmodified as you wished. Hope this helps.
Or else if you want these fields as a reduced json object:
import json
data_json = '{"hostname": "bla","ipaddress": "192.168.1.10","subnetmask": "255.255.255.0","iloip": "192.168.1.11"}'
data = json.loads(data_json)
chosen_fields = ['hostname', 'ipaddress']
reduced_json = "{"
for field in chosen_fields:
reduced_json += f'"{field}": "{data[field]}", '
reduced_json = list(reduced_json)
reduced_json[-2] = "}"
reduced_json = "".join(reduced_json)
reduced = json.loads(reduced_json)
for field in chosen_fields:
print(f'"{field}": "{reduced[field]}"')
Output:
"hostname": "bla"
"ipaddress": "192.168.1.10"
If I understand you correctly:
import json
response = [
{
"hostname": "bla",
"ipaddress": "192.168.1.10",
"subnetmask": "255.255.255.0",
"iloip": "192.168.1.11",
}
]
desired_keys = ["hostname", "ipaddress"]
new_response = json.dumps(
[{key: x[key] for key in desired_keys} for x in response]
)
And now you have a new_response - valid JSON, with which you can continue to work on

How to change values in a json file using JsonPath in python

I have the following Json file: car_models.json
{
"name":"John",
"age":30,
"cars":
[
{
"car_model": "Mustang",
"car_brand": "Ford"
},
{
"car_model": "cx-5",
"car_brand": "Mazda"
}
]
}
I have another json file data_change.json, which contains details about the jsonpath and their values:
{
"testcase_ID": "test_1A",
"description": "Some description",
"request_change_data": [
{
"element_path": "$.cars.[0].car_model",
"element_value": "focus"
}
]
}
I want to read the data_change.json content, use the element_path from here, parse through car_models.json and update its value to the value from data_change.json.
As in, I want to use the jsonPath - $cars[0].car_model, parse through car_models.json, and change the value of car_model from Mustang to focus. So my updated car_models.json should be the following:
{
"name":"John",
"age":30,
"cars":
[
{
"car_model": "focus",
"car_brand": "Ford"
},
{
"car_model": "cx-5",
"car_brand": "Mazda"
}
]
}
How can I do this in python?
guessing that the Expected answer needs to have "focus" and not "ford"
The following should give you this:
import json
import re
with open('cars_model.json') as f:
cars_model = json.load(f)
with open('data_change.json') as f:
data_change = json.load(f)
for elements in data_change['request_change_data']:
element_path = elements['element_path']
#Reg ex to get you the number (as a string) between the square brackets
position_match = re.match(r"^.*\[(.*)\].*$", element_path)
position = int(position_match.group(1))
print position
# Split on "period" to get the thing to match
thing_to_change = element_path.split(".")[1]
print thing_to_change
value = elements['element_value']
print value
cars_model['cars'][0][thing_to_change] = value
print cars_model

Parsing a nested JSON keys and getting the values in a CSV format

I have a nested JSON data like this of about 5000 records.
{
"data": {
"attributes": [
{
"alert_type": "download",
"severity_level": "med",
"user": "10.1.1.16"
},
{
"alert_type": "download",
"severity_level": "low",
"user": "10.2.1.18"
}
]
}
}
Now , I need to parse this JSON and get only certain fields in a CSV format. Let's we would need alert_type & user in a CSV format.
I tried to parse this JSON dictionary:
>>> import json
>>> resp = '{"data":{"attributes":[{"alert_type":"download","severity_level":"med","user":"10.1.1.16"},{"alert_type":"download","severity_level":"low","user":"10.2.1.18"}]}}'
>>> user_dict = json.loads(resp)
>>> event_cnt = user_dict['data']['attributes']
>>> print event_cnt[0]['alert_type']
download
>>> print event_cnt[0]['user']
10.1.1.16
>>> print event_cnt[0]['alert_type'] + "," + event_cnt[0]['user']
download,10.1.1.16
>>>
How to get all the elements/values of a particular keys in a CSV format and in a single iteration ?
Output:
download,10.1.1.16
download,10.2.1.18
Simple list comprehension:
>>> jdict=json.loads(resp)
>>> ["{},{}".format(d["alert_type"],d["user"]) for d in jdict["data"]["attributes"]]
['download,10.1.1.16', 'download,10.2.1.18']
Which you can join for your desired output:
>>> li=["{},{}".format(d["alert_type"],d["user"]) for d in jdict["data"]["attributes"]]
>>> print '\n'.join(li)
download,10.1.1.16
download,10.2.1.18
Since {"data":{"attributes": is a list, you can loop over it and print the values for desired keys (d is the user dict):
for item in d['data']['attributes']:
print(item['alert_type'],',',item['user'], sep='')
You could make it somewhat data-driven like this:
import json
DESIRED_KEYS = 'alert_type', 'user'
resp = '''{ "data": {
"attributes": [
{
"alert_type": "download",
"severity_level": "med",
"user": "10.1.1.16"
},
{
"alert_type": "download",
"severity_level": "low",
"user": "10.2.1.18"
}
]
}
}
'''
user_dict = json.loads(resp)
for attribute in user_dict['data']['attributes']:
print(','.join(attribute[key] for key in DESIRED_KEYS))
To handle attributes that don't have all the keys, you could instead use this as the last line which will assign missing values a default value (such as a blank string as shown) instead of it causing an exception.
print(','.join(attribute.get(key, '') for key in DESIRED_KEYS))
Using jq, a one-line solution is straightforward:
$ jq -r '.data.attributes[] | [.alert_type, .user] | #csv' input.json
"download","10.1.1.16"
"download","10.2.1.18"
If you don't want the strings to be quoted, use join(",") instead of #csv

KeyError: 'Bytes_Written' python

I do not understand why I get this error Bytes_Written is in the dataset but why can't python find it? I am getting this information(see dataset below) from a VM, I want to select Bytes_Written and Bytes_Read and then subtract the previous values from current value and print a json object like this
{'Bytes_Written': previousValue-currentValue, 'Bytes_Read': previousValue-currentValue}
here is what the data looks like:
{
"Number of Devices": 2,
"Block Devices": {
"bdev0": {
"Backend_Device_Path": "/dev/disk/by-path/ip-192.168.26.1:3260-iscsi-iqn.2010-10.org.openstack:volume-d1c8e7c6-8c77-444c-9a93-8b56fa1e37f2-lun-010.0.0.142",
"Capacity": "2147483648",
"Guest_Device_Name": "vdb",
"IO_Operations": "97069",
"Bytes_Written": "34410496",
"Bytes_Read": "363172864"
},
"bdev1": {
"Backend_Device_Path": "/dev/disk/by-path/ip-192.168.26.1:3260-iscsi-iqn.2010-10.org.openstack:volume-b27110f9-41ba-4bc6-b97c-b5dde23af1f9-lun-010.0.0.146",
"Capacity": "2147483648",
"Guest_Device_Name": "vdb",
"IO_Operations": "93",
"Bytes_Written": "0",
"Bytes_Read": "380928"
}
}
}
This is the complete code that I am running.
FIELDS = ("Bytes_Written", "Bytes_Read", "IO_Operation")
def counterVolume_one(state):
url = 'http://url'
r = requests.get(url)
data = r.json()
for field in FIELDS:
state[field] += data[field]
return state
state = {"Bytes_Written": 0, "Bytes_Read": 0, "IO_Operation": 0}
while True:
counterVolume_one(state)
time.sleep(1)
for field in FIELDS:
print("{field:s}: {count:d}".format(field=field, count=state[field]))
counterVolume_one(state)
Your returned JSON structure does not have any of these FIELDS = ("Bytes_Written", "Bytes_Read", "IO_Operation") keys directly.
You'll need to modify your code slightly.
data = r.json()
for block_device in data['Block Devices'].iterkeys():
for field in FIELDS:
state[field] += int(data['Block Devices'][block_device][field])

Categories