I am trying to access the second value in list created from a json object. When accessing the first value"name" I have no problems. But when trying to access "address" i get a error
Result: Failure
Exception: KeyError: 'address'
The json coming in looks like this
{
"DataToCompare": [
{
"name": "Alex Young",
"address": "123 Main Street"
}
],
"DataSetAgainst": [
{
"name": "Bob Doll",
"address": "555 South Street"
},
{
"name": "Bob Young",
"adress": "123 Main St."
}
]
}
In the example below dataBack["address"] = i["address"] is where the error comes in. If I comment it out I get results back for name and name match
def processing_request(dataIncoming):
data_to_compare = dataIncoming["DataToCompare"][0]
dataList = []
for i in dataIncoming["DataSetAgainst"]:
dataList.append(i)
dataResults = []
for i in dataList:
dataBack = {}
clean_name = ''.join(e for e in i["name"] if e.isalnum())
sequence = difflib.SequenceMatcher(isjunk=None, a=data_to_compare["name"], b=clean_name)
difference = sequence.ratio()*100
difference = round(difference, 1)
# works
dataBack["name"] = i["name"]
dataBack["name match"] = difference
# doesnt work
dataBack["address"] = i["address"]
dataResults.append(dataBack)
return json.dumps(dataResults)
The error appears to be a result of a typo:
{
"DataToCompare": [
{
"name": "Alex Young",
"address": "123 Main Street"
}
],
"DataSetAgainst": [
{
"name": "Bob Doll",
"address": "555 South Street"
},
{
"name": "Bob Young",
"address": "123 Main St."
}
]
}
What did I fix: "adress": "123 Main St." to "address": "123 Main St."
Output for the code you shared in this case:
'[{"name": "Bob Doll", "name match": 11.8, "address": "555 South Street"}, {"name": "Bob Young", "name match": 55.6, "address": "123 Main St."}]'
From the things I see, the error is caused because of a mistake in a:
"address": "123 Main St."
line. But let's give a benefit of a doubt and assume that data is corrupted and we want to get a workaround for it.
We could transform our i value into a list of values in the following way:
tab = []
for key in i:
value = i[key]
tab.append(value)
If we now give order to print tabs, we get in the output:
['Bob Doll', '555 South Street']
['Bob Young', '123 Main St.']
So, instead of solution above, you could write last line as:
dataBack["name"], dataBack["address"] = tab
dataBack["name match"] = "cookies"
As a full answer following your script:
def processing_request(dataIncoming):
data_to_compare = dataIncoming["DataToCompare"][0]
dataList = []
for i in dataIncoming["DataSetAgainst"]:
dataList.append(i)
dataResults = []
for i in dataList:
dataBack = {}
clean_name = ''.join(e for e in i["name"] if e.isalnum())
sequence = difflib.SequenceMatcher(isjunk=None, a=data_to_compare["name"], b=clean_name)
difference = sequence.ratio()*100
difference = round(difference, 1)
tab = [i[key] for key in i]
# works
dataBack["name"], dataBack["address"] = tab
dataBack["name match"] = difference
dataResults.append(dataBack)
return json.dumps(dataResults)
Related
The dictionary I am trying to iterate through has the following structure:
d = {
"main_key_1": {
"name": "Name1",
"context": "Context1",
"message": "Message1",
"date": "Date1",
"reference": "Reference1"
},
"main_key_2": {
"name": "Name2",
"context": "Context2",
"message": "Message2",
"date": "Date2",
"reference": "Reference2"
}
}
This is the way I tried to iterate:
for item in d.items():
from_context = f"from {item[1]['context']}"
with context('given a descriptor'):
with context(from_context):
with before.all:
self.descriptor = item[1]['message']
with context('that contains a date'):
with it('recognizes the date'):
adapter = MessageToDatetAdapter(self.descriptor)
result = adapter.is_a_date()
expect(result).to(equal(True))
with it('extracts the date data'):
adapter = MessageToDatetAdapter(self.descriptor)
result = adapter.adapt()
expect(result['date']).to(equal(item[1]['date']))
expect(result['reference']).to(item[1]['reference'])
The first iteration would be something like below:
with context('given a descriptor'):
with context('from Context1'):
with before.all:
self.descriptor = 'Message1'
with context('that contains a date'):
with it('recognizes the date'):
adapter = MessageToDatetAdapter(self.descriptor)
result = adapter.is_a_date()
expect(result).to(equal(True))
with it('extracts the date data'):
adapter = MessageToDatetAdapter(self.descriptor)
result = adapter.adapt()
expect(result['date']).to('Date1')
expect(result['reference']).to('Reference1')
However, it seems like this is not correct. It looks like I cannot iterate through all the dictionary items.
Im new in python but always trying to learn.
Today I got this error while trying select a key from dictionary:
print(data['town'])
KeyError: 'town'
My code:
import requests
defworld = "Pacera"
defcity = 'Svargrond'
requisicao = requests.get(f"https://api.tibiadata.com/v2/houses/{defworld}/{defcity}.json")
data = requisicao.json()
print(data['town'])
The json/dict looks this:
{
"houses": {
"town": "Venore",
"world": "Antica",
"type": "houses",
"houses": [
{
"houseid": 35006,
"name": "Dagger Alley 1",
"size": 57,
"rent": 2665,
"status": "rented"
}, {
"houseid": 35009,
"name": "Dream Street 1 (Shop)",
"size": 94,
"rent": 4330,
"status": "rented"
},
...
]
},
"information": {
"api_version": 2,
"execution_time": 0.0011,
"last_updated": "2017-12-15 08:00:00",
"timestamp": "2017-12-15 08:00:02"
}
}
The question is, how to print the pairs?
Thanks
You have to access the town object by accessing the houses field first, since there is nesting.
You want print(data['houses']['town']).
To avoid your first error, do
print(data["houses"]["town"])
(since it's {"houses": {"town": ...}}, not {"town": ...}).
To e.g. print all of the names of the houses, do
for house in data["houses"]["houses"]:
print(house["name"])
As answered, you must do data['houses']['town']. A better approach so that you don't raise an error, you can do:
houses = data.get('houses', None)
if houses is not None:
print(houses.get('town', None))
.get is a method in a dict that takes two parameters, the first one is the key, and the second parameter is ghe default value to return if the key isn't found.
So if you do in your example data.get('town', None), this will return None because town isn't found as a key in data.
I'm trying to return data to Django model, from Overpass API JSON data after downloaded
"elements": [
{
"type": "node",
"id": 662934404,
"lat": 35.572157,
"lon": 45.3898839,
"tags": {
"addr:postcode": "46001",
"name": "City Center",
"name:en": "City Center Mall",
"name:ku": "City Center Mall",
"shop": "mall",
"website": "http://www.citycentersul.com"
}
},
{
"type": "node",
"id": 2413990402,
"lat": 35.5014386,
"lon": 45.4457576,
"tags": {
"addr:city": "sulaymaniyah",
"designation": "ASSAN",
"name": "ASSAN STEEL CO.",
"opening_hours": "3 min",
"shop": "doityourself",
"source": "ASSAN Steel Company General Trading Co, Ltd"
},
{
"type": "node",
"id": 2414374708,
"lat": 35.506121,
"lon": 45.4417229,
"tags": {
"addr:city": "sulaymaniyah",
"name:ku": "ASSAN Steel Company General Trading Co, Ltd",
"shop": "doityourself",
}
},
but some of the data dosent have both of them together name , name:ku ,name:en
so what should i do if name is none then return name:ku , if its exists then name:en
i've tried this but doesnt work
with open('data.json') as datafile:
objects = json.load(datafile)
for obj in objects['elements']:
try:
objType = obj['type']
if objType == 'node':
tags = obj['tags']
name = tags.get('name')
if not name:
name = tags.get('name:en')
elif not name:
name = tags.get('name:ku')
elif not name:
name = tags.get('name:ar')
else:
name = tags.get('shop','no-name')
is there something else I've missed?
thanks for helping
You could loop over all possible keys and stop after a value was detected:
with open('data.json') as datafile:
objects = json.load(datafile)
for obj in objects['elements']:
objType = obj['type']
if objType == 'node':
tags = obj['tags']
name = None
for nameId in ('name', 'name:en', 'name:ku', 'name:ar'):
if nameId in tags:
name = tags[name]
break # stop looping, we got a name value
# Set default if no key was found
if not name:
name = tags.get('shop','no-name')
The following and all subsequent elif-conditions are wrong:
name = tags.get('name')
if not name:
name = tags.get('name:en')
elif not name:
name = tags.get('name:ku')
elif applies to all previous conditions and gets only executed if all of the previous conditions evaluated to false. In your case, however, the first if-condition (if not name) already evaluated to true. Therefore your elif-conditions won't get executed. You need to change them to if-conditions instead:
name = tags.get('name')
if not name:
name = tags.get('name:en')
if not name:
name = tags.get('name:ku')
if not name:
name = tags.get('name:ar')
if not name:
name = tags.get('shop','no-name')
The loop-approach suggested by Maurice in https://stackoverflow.com/a/60810856/1340631 is better, though.
I'm trying to loop through a JSON file using Python and return the name of the object and associated modules for it.
Right now I can basically get the output I want hardcoding the indexes. However, this obviously isn't the right way to do it (the JSON file can vary in length).
Whenever I try to use a loop, I get errors like:
TypeError: string indices must be integers
My JSON file looks like this:
{
"name": "gaming_companies",
"columns": [{
"name": "publisher",
"type": "string",
"cleansing": ["clean_string"]
},
{
"name": "genre",
"type": "string",
"cleansing": ["match_genre", "clean_string"]
},
{
"name": "sales",
"type": "int",
"cleansing": []
}
]
}
My Python code which is 'working' looks like:
import json as js
def cleansing(games_json):
print (games_json['columns'][0]['name'] + " - cleansing:")
[print(i) for i in games_json['columns'][0]['cleansing'] ]
print (games_json['columns'][1]['name'] + " - cleansing:")
[print(i) for i in games_json['columns'][1]['cleansing'] ]
print (games_json['columns'][2]['name'] + " - cleansing:")
[print(i) for i in games_json['columns'][2]['cleansing'] ]
with open(r'C:\Desktop\gamefolder\jsonfiles\games.json') as input_json:
games_json = js.load(input_json)
cleansing(games_json)
The output I'm trying to return is:
publisher
cleansing:
clean_string
genre
cleansing:
match_genre
clean_string
sales
cleansing:
My attempt to loop through them like this:
for x in games_json:
for y in games_json['columns'][x]:
print (y)
Results in:
TypeError: list indices must be integers or slices, not str
games_json shows as a Dict.
Columns shows as a list of dictionaries.
Each object's cleansing attribute shows as a list.
I think this is where my problem is, but I'm not able to get over the hurdle.
The problem with your attempt is using an iterator as a string.
The x in for y in games_json['columns'][x]: is an iterator object and not the strings ['name', 'cleansing'].
You can learn more about python iterators here
As for the case - you might want to iterate over the columns as a separate list.
This code should work
for item in f["columns"]:
print(item["name"])
print("cleansing:")
print(item["cleansing"])
Output-
publisher
cleansing:
['clean_string']
genre
cleansing:
['match_genre', 'clean_string']
sales
cleansing:
[]
This can be one of working solutions as you want to iterate array's elements.
import json
for x in games_json['columns']:
print(x)
print(x['name'])
x = """{
"name": "gaming_companies",
"columns": [{
"name": "publisher",
"type": "string",
"cleansing": ["clean_string"]
},
{
"name": "genre",
"type": "string",
"cleansing": ["match_genre", "clean_string"]
},
{
"name": "sales",
"type": "int",
"cleansing": []
}
]
}"""
x = json.loads(x)
for i in x['columns']:
print(i['name'])
print("cleansing:")
for j in i["cleansing"]:
print(j)
print('\n')
Output
publisher
cleansing:
clean_string
genre
cleansing:
match_genre
clean_string
sales
cleansing:
with open(r'C:\Desktop\gamefolder\jsonfiles\games.json') as input_json:
games_json = js.load(input_json)
for i in games_json['columns']:
print(i['name'])
print("cleansing:")
for j in i["cleansing"]:
print(j)
print('\n')
JSON data:
[
{
"id": 2,
"name": "An ice sculpture",
"price": 12.50,
},
{
"id": 3,
"name": "A blue mouse",
"price": 25.50,
}
]
Expected output:
id - 2
name - An ice sculpture
price - 12.50
Something similar for id = 3.
Update
What I did so far:
content = urllib.request.urlopen(url).read().decode('utf-8')
content = content.replace("//" , "").strip() #there is a // at the beginning
obj = json.loads(content)
for obj in content:
for key, value in obj.items():
print (obj.key, obj.value)
Error:
File "test.py", line 22, in get
for key, value in obj.items():
AttributeError: 'str' object has no attribute 'items'
I've seen mostly data is accessed directly using the attribute keys like obj[0]["id"] outputs 2. Is there any way I can get the expected output without accessing the keys explicitly?
You have a list of dictionaries. Your code would work, as long as you iterate through the outer list:
for obj in my_json_data:
for key, value in obj.items():
print (obj.key, obj.value)
you should try this
data = [
{
"id": 2,
"name": "An ice sculpture",
"price": 12.50,
},
{
"id": 3,
"name": "A blue mouse",
"price": 25.50,
}
]
for json_data in data:
for k, v in json_data.items():
print('{} - {}'.format(k,v))