Getting a specific element from a JSON string - python

I have a JSON string that i got into python that looks something like this:
{"count": 100,
"facets": null,
"previous_page": null,
"results": [{"updated_at": "2013-09-17T13:45:13Z", "test_id": 194037042, "customer_id":
203793326, "id": 1954182}]
There are more elements but this is a small cut of what i need. Basically, results has a list of 100 dictionaries that contain the elements above "updated_at, test_id, customer_id, id" What i need to do is the following:
I need to get a list of all of the values of JUST the id. I am not sure how to go about this though, i have tried doing things like:
for i in my_dict['results']:
print i['id']
but i get an error message that says:
print i['id']
TypeError: string indices must be integers
What am i doing wrong?

You are not doing anything obviously wrong. Your data includes 'null' elements which are not proper python. This works fine.
my_dict = {"count": 100,
"facets": None,
"previous_page": None,
"results": [{"updated_at": "2013-09-17T13:45:13Z", "test_id": 194037042, "customer_id": 203793326, "id": 1954182}]
}
for i in my_dict['results']:
print i['id']
The error you have implies that one of your list items is a string and when you are trying to get the ['id'] element the error rightly tells you that list indices (a string is a list of characters) must be integers.

It looks like you haven't loaded the json into Python with json.loads(json_string)
And even after you do that, your "results" dict is actually going to be a list of dicts.
Try this:
import json
json_str = '{"count": 100, "facets": null, "previous_page": null, "results": [{"updated_at": "2013-09-17T13:45:13Z", "test_id": 194037042, "customer_id": 203793326, "id": 1954182}, {"updated_at": "2013-09-18T13:45:13Z", "test_id": 194037043, "customer_id": 203793327, "id": 1954183}]}'
data = json.loads(json_str)
result_ids = [result['id'] for result in data['results'] if 'id' in result]
Output:
[1954182, 1954183]
This code would then output a list containing 1954182 and 1954183.
Use a list comprehension here for greater speed and less lines of code. It also ensures that the result dict has an 'id' attribute before trying to access it.

Related

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.

Printing from a dictionary in Python

I am running a method which returns a dictionary which is formed like the following :
{
"intents": [
{
"name": "goodbye",
"created": "2017-08-18T18:09:36.155Z",
"updated": "2017-08-18T18:09:41.755Z",
"description": null
},
{
"name": "hello",
"created": "2017-08-18T18:05:48.153Z",
"updated": "2017-08-18T18:06:06.004Z",
"description": null
}
],
"pagination": {
"refresh_url": "/v1/workspaces/9978a49e-ea89-4493-b33d-82298d3db20d/intents?version=2017-08-21"
}
}
This is all saved in a variable called response, which contains the dictionary for over 200 values.
If I print just "response", it prints all of the above, including "created/updated/description". I just want to print out the name value...and I cannot figure out how to do it.
I have read some posts here and tried the following -
for value in response:
print(value['intent'])
but similarly, this prints out everything (including description/update date etc).
How can I make it only print out the name?
And for a bonus, how can I add the list of names into an array which I can then iterate over?
It appears you want to access the name attribute of each sub-dict in intents. This should work -
for d in response['intents']:
print(d['name'])
If you want this stored in a list, use a list comprehension:
names = [d['name'] for d in response['intents']]
Adding names into list and print it:
names = [intent["name"] for intent in response["intents"]]
print(*names, sep='\n')
Have a look at my solution
names_list = []
for x in response["intents"]:
print x["name"] # it will print all of your names
names_list.append(x["name"]) # it will add the names into the names_list
print names_list
Hope it will help you :)

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.

how to fetch data from json schema? error shown-TypeError: string indices must be integers

I have a json response from an API in this way:-
{
"meta": {
"code": 200
},
"data": {
"username": "luxury_mpan",
"bio": "Recruitment Agents👑👑👑👑\nThe most powerful manufacturers,\nwe have the best quality.\n📱Wechat:13255996580💜💜\n📱Whatsapp:+8618820784535",
"website": "",
"profile_picture": "https://scontent.cdninstagram.com/t51.2885-19/10895140_395629273936966_528329141_a.jpg",
"full_name": "Mpan",
"counts": {
"media": 17774,
"followed_by": 7982,
"follows": 7264
},
"id": "1552277710"
}
}
I want to fetch the data in "media", "followed_by" and "follows" and store it in three different lists as shown in the below code:--
for r in range(1,5):
var=r,st.cell(row=r,column=3).value
xy=var[1]
ij=str(xy)
myopener=Myopener()
url=myopener.open('https://api.instagram.com/v1/users/'+ij+'/?access_token=641567093.1fb234f.a0ffbe574e844e1c818145097050cf33')
beta=json.load(url)
for item in beta['data']:
list1.append(item['media'])
list2.append(item['followed_by'])
list3.append(item['follows'])
When I run it, it shows the error TypeError: string indices must be integers
How would my loop change in order to fetch the above mentioned values?
Also, Asking out of curiosity:- Is there any way to fetch the Watzapp no from the "BIO" key in data dictionary?
I have referred questions similar to this and still did not get my answer. Please help!
beta['data'] is a dictionary object. When you iterate over it with for item in beta['data'], the values taken by item will be the keys of the dictionary: "username", "bio", etc.
So then when you ask for, e.g., item['media'] it's like asking for "username"['media'], which of course doesn't make any sense.
It isn't quite clear what it is that you want: is it just the stuff inside counts? If so, then instead of for item in beta['data']: you could just say item = beta['data']['counts'], and then item['media'] etc. will be the values you want.
As to your secondary question: I suggest looking into regular expressions.

Python and JSON - TypeError list indices must be integers not str

I am learning to use Python and APIs (specifically, this World Cup API, http://www.kimonolabs.com/worldcup/explorer)
The JSON data looks like this:
[
{
"firstName": "Nicolas Alexis Julio",
"lastName": "N'Koulou N'Doubena",
"nickname": "N. N'Koulou",
"assists": 0,
"clubId": "5AF524A1-830C-4D75-8C54-2D0BA1F9BE33",
"teamId": "DF25ABB8-37EB-4C2A-8B6C-BDA53BF5A74D",
"id": "D9AD1E6D-4253-4B88-BB78-0F43E02AF016",
"type": "Player"
},
{
"firstName": "Alexandre Dimitri",
"lastName": "Song-Billong",
"nickname": "A. Song",
"clubId": "35BCEEAF-37D3-4685-83C4-DDCA504E0653",
"teamId": "DF25ABB8-37EB-4C2A-8B6C-BDA53BF5A74D",
"id": "A84540B7-37B6-416F-8C4D-8EAD55D113D9",
"type": "Player"
},
]
I am simply trying to print all of the firstNames in this API. Here's what I have:
import urllib2
import json
url = "http://worldcup.kimonolabs.com/api/players?apikey=xxx"
json_obj = urllib2.urlopen(url).read
readable_json = json.dumps(json_obj)
playerstuff = readable_json['firstName']
for i in playerstuff:
print i['firstName']
But when I run it, I get the error "...line 8, in ...TypeError: list indices must be integers, not str"
I have looked around for solutions, but seem to find questions to more "in depth" API questions and I don't really understand it all yet, so any help or explanation as to what I need to do would be amazing. Thank you!
I solved changing
readable_json['firstName']
by
readable_json[0]['firstName']
First of all, you should be using json.loads, not json.dumps. loads converts JSON source text to a Python value, while dumps goes the other way.
After you fix that, based on the JSON snippet at the top of your question, readable_json will be a list, and so readable_json['firstName'] is meaningless. The correct way to get the 'firstName' field of every element of a list is to eliminate the playerstuff = readable_json['firstName'] line and change for i in playerstuff: to for i in readable_json:.
You can simplify your code down to
url = "http://worldcup.kimonolabs.com/api/players?apikey=xxx"
json_obj = urllib2.urlopen(url).read
player_json_list = json.loads(json_obj)
for player in readable_json_list:
print player['firstName']
You were trying to access a list element using dictionary syntax. the equivalent of
foo = [1, 2, 3, 4]
foo["1"]
It can be confusing when you have lists of dictionaries and keeping the nesting in order.

Categories