Read value from an array of multiple objects (JSON) - python

I'am new to coding and try to build an HTTP-API with python. I have an Array of Objects in JSON format. I want to read a value of one of these objects.
In my python script I append a database table to an array of objects. I am looking for a solution to select a single value in one of these objects.
I have a function:
cur.execute(<SELECT STATEMENT>)
row_headers=[x[0] for x in cur.description]
response = cur.fetchall()
json_data=[]
for result in response:
json_data.append(dict(zip(row_headers,result)))
return jsonify(json_data)
the return looks like:
[
{
"ID": 123,
"CODE": 4117,
"STATUS": "off",
},
{
"ID": 345,
"CODE": 5776,
"STATUS": "on",
}
]
I am looking for a function(inputID):
where ID = inputID
set currentcode = <CODE>
set currentstatus = <STATUS>
<Do something with currentcode and currentstatus>

I believe you're looking for this:
def return_with_id(input_id):
for x in json_data:
if x['ID'] == input_id:
return x
This will loop over every index in json_data and checks to see if the ID of that index is equal to what you asked for, if it finds something that matches, it'll return that and the function completes.
If you want to do other things with this, you can do so by just editing the code the code before it returns.

I think I found the error. I do not exactly know what happend with:
return jsonify(json_data)
But it seems, that this makes my array not usable/iterable. I tried it with
return(json_data)
The output looks the same but know I can use
for x in json_data:

Related

Is there an efficient way to write data to a JSON file using a dictionary in Python?

I'm writing a program in Python to use an API that needs to get input from a JSON payload in a really specific way which is shown below. The poid element will contain a different number with each run of the program, the inventories element contains a list of dictionaries that I am trying to send to the API.
[
{
"poid":"22130",
"inventories":
[
{
"item": "SAMPLE-ITEM-1",
"mfgr": "SAMPLE-MANUFACTURER-1",
"quantity": "1",
"condition": "REF"
},
{
"item": "SAMPLE-ITEM-2",
"mfgr": "SAMPLE-MANUFACTURER-2",
"quantity": "3",
"condition": "REF"
}
]
}
]
The data I need to put into the file is stored in a dictionary and a list as shown below. For simplicity of this post, I'm showing what the dictionary and list would look like after another method creates them. I'm not sure if this is the most efficient way of storing this data when I'm having to write it to JSON.
pn_and_mfgr_dict = {'SAMPLE-ITEM-1': 'SAMPLE-MANUFACTURER-1', 'SAMPLE-ITEM-2': 'SAMPLE-MANUFACTURER-2'}
quantities = ["1","3"]
poid = 22130 #this will be different each run
If it makes sense from what I've written above, I need to generate a JSON file that looks like the first codeblock given the information from the second codeblock. The item at index 0 in the quantities list corresponds to the first key/value pair in the dictionary and so on. The "condition" value in the first codeblock will always have "REF" as its value for my use, but I need to also include that in the final payload that gets sent to the API. Since the part number and manufacturer dictionary will be a different length with each run, I also need this method to work regardless of how many values are in the dictionary. This dictionary and the quantities list will always be the same length though. I think the best way I can solve this is making a for loop that iterates through the dictionary and puts respective data where it needs to be, then reading the file when the for loop is done and sending it as the payload but please correct me if there's a better way to do this like storing everything in variables. I also have no experience with JSON so I have attempted to use JSON libraries to accomplish this with no idea what I'm doing wrong. I can edit this with my attempts tonight but I wanted to post this as soon as possible.
Here is one possible solution:
import json
pn_and_mfgr_dict = {
'SAMPLE-ITEM-1': 'SAMPLE-MANUFACTURER-1',
'SAMPLE-ITEM-2': 'SAMPLE-MANUFACTURER-2'
}
quantities = ['1', '3']
poid = 22130
payload = {
'poid': poid,
'inventories': [{
'item': item,
'mfgr': mfgr,
'quantity': quantity,
'condition': 'REF'
} for (item, mfgr), quantity in zip(pn_and_mfgr_dict.items(), quantities)]
}
print(json.dumps(payload, indent=2))
The code above will result in:
{
"poid": 22130,
"inventories": [
{
"item": "SAMPLE-ITEM-1",
"mfgr": "SAMPLE-MANUFACTURER-1",
"quantity": "1",
"condition": "REF"
},
{
"item": "SAMPLE-ITEM-2",
"mfgr": "SAMPLE-MANUFACTURER-2",
"quantity": "3",
"condition": "REF"
}
]
}
Naturally, you can adjust that for multiple poids with something like this:
poids = [22130, 22131, 22132]
for poid in poids:
# implement here the logic to get items and quantities for
# each poid
payload = {
'poid': poid,
'inventories': [{
'item': item,
'mfgr': mfgr,
'quantity': quantity,
'condition': 'REF'
} for (item, mfgr), quantity in zip(pn_and_mfgr_dict.items(), quantities)]
}
print(json.dumps(payload, indent=2))
You will need to change it to have the correspondents items and quantities for each poid, and I leave that as starting point for you to implement.
Your second block is your input, so you could immediately start by write down a function taking those input and returning a JSON string.
import json
from typing import Dict, List
def jsonify_data(pn_and_mfgr_dict: Dict, quantities: List, poid: int):
constructed_data = [] # TODO
return json.dumps(constructed_data)
Then you could start working on using the inputs to construct the output data you desired. And you already know how to do it.
I think the best way I can solve this is making a for loop that iterates through the dictionary and puts respective data where it needs to be
Yes, that's the way to do it.
Here's my version of solution:
import json
from typing import Dict, List
def jsonify_data(pn_and_mfgr_dict: Dict, quantities: List, poid: int):
inventories = [
{
'item': item,
'mfgr': mfgr,
'quantity': quantity,
'condition': 'REF',
} for (item, mfgr), quantity in zip(pn_and_mfgr_dict.items(), quantities)
]
constructed_data = [
{
'poid': f'{poid}',
'inventories': inventories,
}
]
return json.dumps(constructed_data)
import json
data = {'inventories': [{'SAMPLE-ITEM-1': 'SAMPLE-MANUFACTURER-1'}, {'SAMPLE-ITEM-2': 'SAMPLE-MANUFACTURER-2'}]}
quantities = ["1", "3"]
poid = 22130
# Add poid to data
data['poid'] = poid
# Add quantities to data
for item in data['inventories']:
item['quantity'] = quantities.pop(0)
# Serializing json
json_object = json.dumps(data, indent=4)
print(json_object)

How do you extract multiple values from JSON?

I have a JSON file like this:
print(resp)
dataList = []
{
"totalCount": 9812,
"pageSize": 50,
"nextPageKey": "12345",
"problems": [
{
"problemId": "1234",
"displayId": "test1",
"title": "host memory saturation",
"impactLevel": "INFRASTRUCTURE",
"severityLevel": "RESOURCE_CONTENTION",
"status": "OPEN"
}
]
}
I need to extract "title", "impactLevel" and "severityLevel" and create a data frame out this:
I have tried this:
dataList.append([resp['problems'][0]['title']['impactLevel']['severityLevel']])
hyperEntitydf = pd.DataFrame(dataList, columns=['Alert','Type','Severity'])
hyperEntitydf=hyperEntitydf.drop_duplicates()
print(hyperEntitydf.head())
On this line:
dataList.append([resp['problems'][0]['title']['impactLevel']['severityLevel']])
I am getting this error:
TypeError: string indices must be integers
Is it possible to extract multiple fields with one call?
dataList.append([resp['problems'][0]['title']['impactLevel']['severityLevel']])
No, it's not possible. For this to work, the json would need to be nested such that impactLevel were within title, and severityLevel were within impactLevel.
I'd suggest
x = resp['problems'][0]
dataList.append([x['title'], x['impactLevel', x['severityLevel'])
Unless, you want all the fields of the json, in which case you can do:
dataList.append(list(resp['problems'][0].values()))
Use operators.itemgetter:
from operator import itemgetter
f = itemgetter('title', 'impactLevel', 'severityLevel')
dataList.append(list(f(resp['problems'][0])))
You only need to use list if you specifically need a list; f will return a tuple.
If you want the three values from every element of resp['problems'],
dataList = list(map(f, resp['problems']))
Here, you only need list if DataFrame requires a list, rather than an arbitrary iterable.

Python3 - Parse list of strings inside nested json

Python Noob here. I saw many similar questions but none of it my exact use case. I have a simple nested json, and I'm trying to access the element name present inside metadata. Below is my sample json.
{
"items": [{
"metadata": {
"name": "myname1"
}
},
{
"metadata": {
"name": "myname1"
}
}
]
}
Below is the code That I have tried so far, but not successfull.
import json
f = open('./myfile.json')
x = f.read()
data = json.loads(x)
for i in data['items']:
for j in i['metadata']:
print (j['name'])
It errors out stating below
File "pythonjson.py", line 8, in
print (j['name']) TypeError: string indices must be integers
When I printed print (type(j)) I received the following o/p <class 'str'>. So I can see that it is a list of strings and not an dictinoary. So now How can I parse through a list of strings? Any official documentation or guide would be much helpful to know the concept of this.
Your json is bad, and the python exception is clear and unambiguous. You have the basic string "name" and you are trying to ... do a lookup on that?
Let's cut out all the json and look at the real issue. You do not know how to iterate over a dict. You're actually iterating over the keys themselves. If you want to see their values too, you're going to need dict.items()
https://docs.python.org/3/tutorial/datastructures.html#looping-techniques
metadata = {"name": "myname1"}
for key, value in metadata.items():
if key == "name":
print ('the name is', value)
But why bother if you already know the key you want to look up?
This is literally why we have dict.
print ('the name is', metadata["name"])
You likely need:
import json
f = open('./myfile.json')
x = f.read()
data = json.loads(x)
for item in data['items']:
print(item["metadata"]["name"]
Your original JSON is not valid (colons missing).
to access contents of name use "i["metadata"].keys()" this will return all keys in "metadata".
Working code to access all values of the dictionary in "metadata".
for i in data['items']:
for j in i["metadata"].keys():
print (i["metadata"][j])
**update:**Working code to access contents of "name" only.
for i in data['items']:
print (i["metadata"]["name"])

Reference all indexes in list and check for existence of value in python

I'm trying to create if block in my python3 script that checks if a value exists within a list I pull from JSON. The JSON data is below:
[
{
"id": 59616405645,
"name": "Foo"
},
{
"id": 990164054345,
"name": "FindMe"
},
{
"id": 2009167874,
"name": "Bar"
}
]
I'm trying to determine whether or not the value of Bar exists within the list. To do so I'm doing the following which directly references the index:
if "FindMe" in m_orgs[1].values():
print("Yo it's here")
else:
print("Yo it's not here.")
But the JSON data I'm pulling will always have different results and we will never know the index numbers, so direct reference will not work. How do I reference all indexes in a list at once?
You can't reference all indexes at once, but you can loop through them, and stop as soon as you find the first existence. Something like:
found = any("findMe" in item.values() for item in m_orgs)
This line will stop the execution when it finds the first True value. So worst case, it will look through every position and not find anything.
You can use any() like this:
if any(d['name'] == 'Foo' for d in json):
do this
You can first translate the original json data to set of data, and then simply check through set operations,
name_set = {org['name'] for org in m_orgs}
print 'FindMe' in name_set

Python - Searching JSON

I have JSON output as follows:
{
"service": [{
"name": ["Production"],
"id": ["256212"]
}, {
"name": ["Non-Production"],
"id": ["256213"]
}]
}
I wish to find all ID's where the pair contains "Non-Production" as a name.
I was thinking along the lines of running a loop to check, something like this:
data = json.load(urllib2.urlopen(URL))
for key, value in data.iteritems():
if "Non-Production" in key[value]: print key[value]
However, I can't seem to get the name and ID from the "service" tree, it returns:
if "Non-Production" in key[value]: print key[value]
TypeError: string indices must be integers
Assumptions:
The JSON is in a fixed format, this can't be changed
I do not have root access, and unable to install any additional packages
Essentially the goal is to obtain a list of ID's of non production "services" in the most optimal way.
Here you go:
data = {
"service": [
{"name": ["Production"],
"id": ["256212"]
},
{"name": ["Non-Production"],
"id": ["256213"]}
]
}
for item in data["service"]:
if "Non-Production" in item["name"]:
print(item["id"])
Whatever I see JSON I think about functionnal programming ! Anyone else ?!
I think it is a better idea if you use function like concat or flat, filter and reduce, etc.
Egg one liner:
[s.get('id', [0])[0] for s in filter(lambda srv : "Non-Production" not in srv.get('name', []), data.get('service', {}))]
EDIT:
I updated the code, even if data = {}, the result will be [] an empty id list.

Categories