How to add a string to JSON list in python - python

Here is my code sample:
try:
REST_Call = Session.get(CC_URL_REST) #Getting the session for a particular url.
REST_CALL = REST_Call.content #Retrieving the contents from the url.
JSON_Data = json.loads(REST_CALL) #Loading data as JSON.
Report_JSON.append(JSON_Data) #Appending the data to an empty list
The JSON data that is returned and appended to the 'Report_JSON' is:
[
{
"content": [
{
"id": 001,
"name": "Sample_Name",
"description": "Sample_description",
"status": "STARTED",
"source": null,
"user": "username"
}
},
],
I just want to add the below data in string format to the above JSON list:
{
"CronExpression": "0 1,30 4,5,6,7,8,9,10,11,12,13,14 ? * 2,3,4,5,6"
},
Sample code for the above string data:
Cron_Call = Session.get(Cron_URL_REST)
Cron_CALL = Cron_Call.content
Cron_Data = json.loads(Cron_CALL)
cron_value = Cron_Data["cronExpression"]
Report_JSON.append({
"CronExpression": cron_value
})
When trying to append it to the 'Report_JSON' this is the output I get:
[
{
"content": [
{
"id": 001,
"name": "Sample_Name",
"description": "Sample_description",
"status": "STARTED",
"source": null,
"user": "username"
}
},
],
{
"CronExpression": "0 1,30 4,5,6,7,8,9,10,11,12,13,14 ? * 2,3,4,5,6"
},
I'm trying to show both the data's under the same "content" tab unlike it being separate.
This is the result i'm trying to get:
{
"id": 001,
"name": "Sample_Name",
"description": "Sample_description",
"status": "STARTED",
"source": null,
"user": "username"
"CronExpression": "0 1,30 4,5,6,7,8,9,10,11,12,13,14 ? * 2,3,4,5,6"
},
Any ideas on how to implement it?

Loop over JSON_Data['content'] and add the new key to each of them.
Cron_Call = Session.get(Cron_URL_REST)
Cron_CALL = Cron_Call.content
Cron_Data = json.loads(Cron_CALL)
cron_value = Cron_Data["cronExpression"]
for x in JSON_DATA['content']:
x['CronExpression'] = cron_value

Here, Report_JSON is loaded as a list type in Python (JSON data can be interpreted by Python as either a list, if it is surrounded by [] square brackets, or a dict if it is surrounded by {} curly brackets).
When you call Report_JSON.append(), it will append a new item to the list. You are creating a new dictionary with a single key-value pair (CronExpression) and adding it to the list, which is why the two dictionaries are side-by-side.
What you should do instead is get the first item in the Report_JSON list, which is the dictionary; then ask for the value corresponding to the content key, which will be a list; then ask for the first item in that list, which will be the dictionary you want to modify (with keys id, name, description, etc.)
Modify that dictionary, then put it back in the list. Here's the code that will do that:
# Get first item in Report_JSON list
content_dict = Report_JSON[0]
# Get the value corresponding to the 'content' key, which is a list
content_value = content_dict['content']
# Get the first item in the list, which is the dict you want to modify
dict_to_modify = content_value[0]
# Now add your new key-value pair
dict_to_modify['CronExpression'] = "0 1,30 4,5,6,7 ..."
Or, to do it in one shot:
Report_JSON[0]['content'][0]['CronExpression'] = "0 1,30 4,5,6,7 ..."
UPDATE: If the "content" list has multiple items, you can iterate over each item in that list:
for content_dict in Report_JSON[0]['content']:
content_dict['CronExpression'] = "0 1,30 4,5,6,7 ..."
which will result in something like this:
[
{
"content": [
{
"id": 001,
"name": "Sample_Name",
"description": "Sample_description",
"status": "STARTED",
"source": null,
"user": "username",
"CronExpression": "0 1,30 4,5,6,7 ..."
},
{
"id": 002,
"name": "Another_Sample_Name",
"description": "Another_sample_description",
"status": "STARTED",
"source": null,
"user": "another_username",
"CronExpression": "0 1,30 4,5,6,7 ..."
},
]
},
],
UPDATE 2: If you are not interested in keeping the original structure and you want to strip everything up to and including the "content" key, you can just do this to start off:
Report_JSON = Report_JSON[0]['content']
and Report_JSON is now just the inner "content" list.

Related

How to iterate through a nested list in python?

I want to iterate through a list that has a lot of dictionaries inside it. The json response I'm trying to iterate looks something like this:
user 1 JSON response:
[
{
"id": "333",
"name": "hello"
},
{
"id": "999",
"name": "hi"
},
{
"id": "666",
"name": "abc"
},
]
user 2 JSON response:
[
{
"id": "555",
"name": "hello"
},
{
"id": "1001",
"name": "hi"
},
{
"id": "26236",
"name": "abc"
},
]
This is not the actual JSON response but it is structured the same way. What I'm trying to do is to find a specific id and store it in a variable. The JSON response I'm trying to iterate is not organized and changes every time depending on the user. So I need to find the specific id which would be easy but there are many dictionaries inside the list. I tried iterating like this:
for guild_info in guilds:
for guild_ids in guild_info:
This returns the first dictionary which is id: 333. For example, I want to find the value 666 and store it in a variable. How would I do that?
What you have is a list of dictionaries.
When you run for guild_info in guilds: you will iterate through dictionaries, so here each guild_info will be a dictionary. Therefore simply take the key id like so: guild_info['id'].
If what you want to do is find the name corresponding to a specific id, you can use list comprehension and take its first element, as follows:
name = [x['name'] for x in guilds if x['id'] == '666'][0]
Here's a function that will search only until it finds the matching id and then return, which avoids checking further entries unnecessarily.
def get_name_for_id(user, id_to_find):
# user is a list, and each guild in it is a dictionary.
for guild in user:
if guild['id'] == id_to_find:
# Once the matching id is found, we're done.
return guild['name']
# If the loop completes without returning, then there was no match.
return None
user = [
{
"id": "333",
"name": "hello"
},
{
"id": "999",
"name": "hi"
},
{
"id": "666",
"name": "abc"
},
]
name = get_name_for_id(user, '666')
print(name)
name2 = get_name_for_id(user, '10000')
print(name2)
Output:
abc
None
This will create a loop which will iterate to the list of dictionaries.If you are looking for simple approach
for every_dictionary in List_of_dictionary:
for every_dictionary_item in every_dictionary.keys():
print(every_dictionary[every_dictionary_item])

Very nested JSON with optional fields into pandas dataframe

I have a JSON with the following structure. I want to extract some data to different lists so that I will be able to transform them into a pandas dataframe.
{
"ratings": {
"like": {
"average": null,
"counts": {
"1": {
"total": 0,
"users": []
}
}
}
},
"sharefile_vault_url": null,
"last_event_on": "2021-02-03 00:00:01",
],
"fields": [
{
"type": "text",
"field_id": 130987800,
"label": "Name and Surname",
"values": [
{
"value": "John Smith"
}
],
{
"type": "category",
"field_id": 139057651,
"label": "Gender",
"values": [
{
"value": {
"status": "active",
"text": "Male",
"id": 1,
"color": "DCEBD8"
}
}
],
{
"type": "category",
"field_id": 151333010,
"label": "Field of Studies",
"values": [
{
"value": {
"status": "active",
"text": "Languages",
"id": 3,
"color": "DCEBD8"
}
}
],
}
}
For example, I create a list
names = []
where if "label" in the "fields" list is "Name and Surname" I append ["values"][0]["value"] so names now contains "John Smith". I do exactly the same for the "Gender" label and append the value to the list genders.
The above dictionary is contained in a list of dictionaries so I just have to loop though the list and extract the relevant fields like this:
names = []
genders = []
for r in range(len(users)):
for i in range(len(users[r].json()["items"])):
for field in users[r].json()["items"][i]["fields"]:
if field["label"] == "Name and Surname":
names.append(field["values"][0]["value"])
elif field["label"] == "Gender":
genders.append(field["values"][0]["value"]["text"])
else:
# Something else
where users is a list of responses from the API, each JSON of which has the items is a list of dictionaries where I can find the field key which has as the value a list of dictionaries of different fields (like Name and Surname and Gender).
The problem is that the dictionary with "label: Field of Studies" is optional and is not always present in the list of fields.
How can I manage to check for its presence, and if so append its value to a list, and None otherwise?
To me it seems that the data you have is not valid JSON. However if I were you I would try using pandas.json_normalize. According to the documentation this function will put None if it encounters an object with a label not inside it.

Extracting data from JSON depending on other parameters

What are the options for extracting value from JSON depending on other parameters (using python)? For example, JSON:
"list": [
{
"name": "value",
"id": "123456789"
},
{
"name": "needed-value",
"id": "987654321"
}
]
When using json_name["list"][0]["id"] it obviously returns 123456789. Is there a way to indicate "name" value "needed-value" so i could get 987654321 in return?
For example:
import json as j
s = '''
{
"list": [
{
"name": "value",
"id": "123456789"
},
{
"name": "needed-value",
"id": "987654321"
}
]
}
'''
js = j.loads(s)
print [x["id"] for x in js["list"] if x["name"] == "needed-value"]
The best way to handle this is to refactor the json as a single dictionary. Since "name" and "id" are redundant you can make the dictionary with the value from "name" as the key and the value from "id" as the value.
import json
j = '''{
"list":[
{
"name": "value",
"id": "123456789"
},{
"name": "needed-value",
"id": "987654321"
}
]
}'''
jlist = json.loads(j)['list']
d = {jd['name']: jd['id'] for jd in jlist}
print(d) ##{'value': '123456789', 'needed-value': '987654321'}
Now you can iterate the items like you normally would from a dictionary.
for k, v in d.items():
print(k, v)
# value 123456789
# needed-value 987654321
And since the names are now hashed, you can check membership more efficiently than continually querying the list.
assert 'needed-value' in d
jsn = {
"list": [
{
"name": "value",
"id": "123456789"
},
{
"name": "needed-value",
"id": "987654321"
}
]
}
def get_id(list, name):
for el in list:
if el['name'] == name:
yield el['id']
print(list(get_id(jsn['list'], 'needed-value')))
Python innately treats JSON as a list of dictionaries. With this in mind, you can call the index of the list you need to be returned since you know it's location in the list (and child dictionary).
In your case, I would use list[1]["id"]
If, however, you don't know where the position of your needed value is within the list, the you can run an old fashioned for loop this way:
for user in list:
if user["name"] == "needed_value":
return user["id"]
This is assuming you only have one unique needed_value in your list.

Return nested JSON item that has multiple instances

So i am able to return almost all data, except i am not able to capture something like this:
"expand": "schema"
"issues": [
{
"expand": "<>",
"id": "<>",
"self": "<>",
"key": "<>",
"fields": {
"components": [
{
"self": "<>",
"id": "1",
"name": "<>",
"description": "<>"
}
]
}
},
{
"expand": "<>",
"id": "<>",
"self": "<>",
"key": "<>",
"fields": {
"components": [
{
"self": "<>",
"id": "<>",
"name": "<>"
}
]
}
},
I want to return a list that contains both of the 'name's for 'components', i have tried using:
list((item['fields']['components']['name']) for item in data['issues'])
but i get a type error saying TypeError: list indices must be integers or slices, not str when i try to Print() the above line of code
Also, if i could get some explanation of what this type error means, and what "list" is trying to do that means that it is not a "str" that would be appreciated
EDIT:
url = '<url>'
r = http.request('GET', url, headers=headers)
data = json.loads(r.data.decode('utf-8'))
print([d['name'] for d in item['fields']['components']] for item in data['issues'])
As the commenter points out you're treating the list like a dictionary, instead this will select the name fields from the dictionaries in the list:
list((item['fields']['components'][i]['name'] for i, v in enumerate(item['fields']['components'])))
Or simply:
[d['name'] for d in item['fields']['components']]
You'd then need to apply the above to all the items in the iterable.
EDIT: Full solution to just print the name fields, assuming that "issues" is a key in some larger dictionary structure:
for list_item in data["issues"]: # issues is a list, so iterate through list items
for dct in list_item["fields"]["components"]: # each list_item is a dictionary
print(dct["name"]) # name is a field in each dictionary

How to print more than one value from nested dict in Python

I am trying to parse output from Get API. My response text is:
{
"data": [
{
"date_created": "22:20:47",
"name": "test1",
"id": "12345",
"status": "0"
},
{
"date_created": "00:09:17",
"name": "test2",
"id": "23456",
"status": "0"
},
{
"date_created": "00:08:02",
"name": "test3",
"id": "34567",
"status": "0"
},
I have ~100 ids. I need to print only ids and search for specific id from list.
so far, i parse with next method:
json_data = get_req.text
python_data = json.loads(json_data)
id = python_data["data"][0]["id"]
print "Object id: ", id
But it is printing only one ID, where i need all of them.
Do you have any ideas how can i print all of them?
Try using this below code snippet:
for i in range(len(python_data["data"])):
print(python_data["data"][i]["id"])
I got the expected output :
12345
23456
34567
you have a list of dicts so you need loop:
ids = [x.get('id') for x in python_data["data"]]
print (ids)

Categories