Python - Search and export information from JSON - python

This is the structure of my json file
},
"client1": {
"description": "blabla",
"contact name": "",
"contact email": "",
"third party organisation": "",
"third party contact name": "",
"third party contact email": "",
"ranges": [
"1.1.1.1",
"2.2.2.2",
"3.3.3.3"
]
},
"client2": {
"description": "blabla",
"contact name": "",
"contact email": "",
"third party organisation": "",
"third party contact name": "",
"third party contact email": "",
"ranges": [
"4.4.4.4",
"2.2.2.2"
]
},
I've seen ways to export specific parts of this json file but not everything. Basically all I want to do is search through the file using user input.
All I'm struggling with is how I actually use the user input to search and print everything under either client1 or client2 based on the input? I am sure this is only 1 or 2 lines of code but cannot figure it out. New to python. This is my code
data = json.load(open('clients.json'))
def client():
searchq = input('Client to export: '.capitalize())
search = ('""'+searchq+'"')
a = open('Log.json', 'a+')
a.write('Client: \n')
client()

This should get you going:
# Safely open the file and load the data into a dictionary
with open('clients.json', 'rt') as dfile:
data = json.load(dfile)
# Ask for the name of the client
query = input('Client to export: ')
# Show the corresponding entry if it exists,
# otherwise show a message
print(data.get(query, 'Not found'))

I'm going to preface this by saying this is 100% a drive-by answering, but one thing you could do is have your user use a . (dot) delimited format for specifying the 'path' to the key in the dictionary/json structure, then implementing a recursive function to seek out the value under that path like so:
def get(query='', default=None, fragment=None):
"""
Recursive function which returns the value of the terminal
key of the query string supplied, or if no query
is supplied returns the whole fragment (dict).
Query string should take the form: 'each.item.is.a.key', allowing
the user to retrieve the value of a key nested within the fragment to
an arbitrary depth.
:param query: String representation of the path to the key for which
the value should be retrieved
:param default: If default is specified, returns instead of None if query is invalid
:param fragment: The dictionary to inspect
:return: value of the specified key or fragment if no query is supplied
"""
if not query:
return fragment
query = query.split('.')
try:
key = query.pop(0)
try:
if isinstance(fragment, dict) and fragment:
key = int(key) if isinstance(fragment.keys()[0], int) else key
else:
key = int(key)
except ValueError:
pass
fragment = fragment[key]
query = '.'.join(query)
except (IndexError, KeyError) as e:
return default if default is not None else None
if not fragment:
return fragment
return get(query=query, default=default, fragment=fragment)
There are going to be a million people who come by here with better suggestions than this and there are doubtless many improvements to be made to this function as well, but since I had it lying around I thought I'd put it here, at least as a starting point for you.
Note:
Fragment should probably be made a positional argument or something. IDK. Its not because I had to rip some application specific context out (it used to have a sensible default state) and I didn't want to start re-writing stuff, so I leave that up to you.
You can do some cool stuff with this function, given some data:
d = {
'woofage': 1,
'woofalot': 2,
'wooftastic': ('woof1', 'woof2', 'woof3'),
'woofgeddon': {
'woofvengers': 'infinity woof'
}
}
Try these:
get(fragment=d, query='woofage')
get(fragment=d, query='wooftastic')
get(fragment=d, query='wooftastic.0')
get(fragment=d, query='woofgeddon.woofvengers')
get(fragment=d, query='woofalistic', default='ultraWOOF')
Bon voyage!

Pass the json format into Dict then look into the topic you want and Read or write it
import json
r = {'is_claimed': True, 'rating': 3.5}
r = json.dumps(r) # Here you have json format {"is_claimed": true, "rating": 3.5}
Json to Dict:
loaded_r = json.loads(r) # {'is_claimed': True, 'rating': 3.5}
print (r)#Print json format
print (loaded_r) #Print dict
Read the Topic
Data=loaded_r['is_claimed'] #Print Topic desired
print(Data) #True
Overwrite the topic
loaded_r['is_claimed']=False
And also this would do the same
print(loaded_r['client1']['description'])

Related

Extracting certain value from MongoDB using Python

I have a mongo database including the following collection:
"
"_id": {
"$oid": "12345"
},
"id": "333555",
"token": [
{
"access_token": "ac_33bc",
"expires_in": 3737,
"token_type": "bearer",
"expires_at": {
"$date": "2021-07-02T13:37:28.123Z"
}
}
]
}
In the next python script I'm trying to return and print only the access_token but can't figure out how to do so. I've tried various methods which none of the worked.I've given the "id" as a parameter
def con_mongo():
try:
client = pymongo.MongoClient("mongodb:localhost")
#DB name
db = client["db1"]
#Collection
coll = db["coll1"]
#1st method
x = coll.find({"id":"333555"},{"token":"access_token"})
for data in x:
print(x)
#2nd method
x= coll.find({"id":"333555"})
tok=x.distinct("access_token")
#print(x[0])
for data in tok:
print(data)
except Exception:
logging.info(Exception)
It doesn't work this way, although if I replace (or remove) the "access_token" with simply "token" it works but I get back all the informations included in the field "token" where I only need the value of the "access_token".
Since access_token is an array element, you need to qualify it's name with the name of the array, to properly access its value.
Actually you can first extract the whole document and get the desired value through simple list and dict indexing.
So, assuming you are retrieving many documents with that same id:
x = [doc["token"][0]["access_token"] for doc in coll.find({"id":"333555"})]
The above, comprehensively creates a list with the access_tokens of all the documents matching the given id.
If you just need the first (and maybe only) occurrence of a document with that id, you can use find_one() instead:
x = coll.find_one({"id":"333555"})["token"][0]["access_token"]
# returns ac_33bc
token is a list so you have to reference the list element, e.g.
x = coll.find({"id":"333555"},{"token.access_token"})
for data in x:
print(data.get('token')[0].get('access_token'))
prints:
ac_33bc

How get variable (which does not exist in a message) from JSON message?

I have a JSON message. And I want to return values that stand for "Brand", but in this message it does not exist, so this value needs to be replaced by another. How can I do that? I tried with try/except, however the values are not replaced.
import json
message = [
{
"ID": 48,
"Type": "Update",
"UpdateType": "Quote",
"Key": {
"Service": "Online",
"Name": "Audi"
},
"Fields": {
"Buyers": 1000,
"Sellers": 500,
"Year": 2020
}
}
]
data=json.loads(message)
#data[0]['ID'] this works as there is ID
try:
data[0]['Brand']
except :
9999 #no output seen
From your question:
I want to return values that stand for "Brand", but in this message, the "Brand does not exist, so this value is needed to be replaced by another. How can I do it?
So you want to retrieve entry from a list, then get item from the entry for example Brand.
and if there is no such Brand in the entry then add Brand item to the entry.
Am I right?
if so, your code may changed to:
import json
message = '[{"ID":48,"Type":"Update","UpdateType":"Quote","Key": {"Service":"Online","Name":"Audi"},"Fields":{"Buyers":1000,"Sellers":500,"Year":2020}}]'
data=json.loads(message) # here message should be a json-string
#data[0]['ID'] this works as there is ID
try:
data[0]['Brand']
except KeyError:
# 9999 #no output seen
data[0]['Brand'] = NewItem # the item you want to replace
You need to itinerante thru the list and check in one of then contains the key. This being done on a python objects and not on a raw json string
message = [{"ID":48,"Type":"Update","UpdateType":"Quote","Key":{"Service":"Online","Name":"Audi"},"Fields":{"Buyers":1000,"Sellers":500,"Year":2020}}]
def item_exists_ofd(dic_list, item):
for dic in dic_list:
if item in dic:
return dic
return None
if __name__ == '__main__':
match = item_exists_ofd(message, 'Brand')
if match:
print(match['Brand'])
else:
print('Brand, not found')
match = item_exists_ofd(message, 'ID')
if match:
print(match['ID'])
else:
print('ID, not found')

How to link yaml key values to json key values in python

Hi I would like to essentially use yaml data inside json
for eg.
json file:
{
"Name": "foo",
"Birthdate": "1/1/1991",
"Address": "FOO_ADDRESS",
"Note": "Please deliver package to foo at FOO_ADDRESS using COURIER service"
}
yaml file:
---
FOO_ADDRESS: "foo lane, foo state"
COURIER: "foodex"
Could someone please guide me on the most efficient way to do this? In this particular example I don't really need to use a separate yaml file (I understand that). But in my specific case I might have to do that.
Edit: sorry I didnt paste the desired output file
Should look something like this:
{
"Name": "foo",
"Birthdate": "1/1/1991",
"Address": "foo lane, foo state",
"Note": "Please deliver package to foo at foo lane, foo state using foodex service"
}
To be safe, first load the JSON and then do the replacements in the loaded strings. If you do the replacements in the JSON source, you might end up with invalid JSON output (when the replacement strings contain " or other characters that have to be escaped in JSON).
import yaml, json
def doReplacements(jsonValue, replacements):
if isinstance(jsonValue, dict):
processed = {doReplacements(key, replacements): \
doReplacements(value, replacements) for key, value in \
jsonValue.iteritems()}
# Python 3: use jsonValue.items() instead
elif isinstance(jsonValue, list):
processed = [doReplacements(item, replacements) for item in jsonValue]
elif isinstance(jsonValue, basestring):
# Python 3: use isinstance(jsonValue, str) instead
processed = jsonValue
for key, value in replacements.iteritems():
# Python 3: use replacements.items() instead
processed = processed.replace(key, value)
else:
# nothing to replace for Boolean, None or numbers
processed = jsonValue
return processed
input = json.loads("""{
"Name": "foo",
"Birthdate": "1/1/1991",
"Address": "FOO_ADDRESS",
"Note": "Please deliver package to foo at FOO_ADDRESS using COURIER service"
}
""")
replacements = yaml.safe_load("""---
FOO_ADDRESS: "foo lane, foo state"
COURIER: "foodex"
""")
print json.dumps(doReplacements(input, replacements), indent=2)
# Python 3: `(...)` around print argument
Use json.load and json.dump to read/write files instead of strings. Note that loading and writing the JSON data may change the order of the items in the object (which you should not depend on anyway).

List Indices in json in Python

I've got a json file that I've pulled from a web service and am trying to parse it. I see that this question has been asked a whole bunch, and I've read whatever I could find, but the json data in each example appears to be very simplistic in nature. Likewise, the json example data in the python docs is very simple and does not reflect what I'm trying to work with. Here is what the json looks like:
{"RecordResponse": {
"Id": blah
"Status": {
"state": "complete",
"datetime": "2016-01-01 01:00"
},
"Results": {
"resultNumber": "500",
"Summary": [
{
"Type": "blah",
"Size": "10000000000",
"OtherStuff": {
"valueOne": "first",
"valueTwo": "second"
},
"fieldIWant": "value i want is here"
The code block in question is:
jsonFile = r'C:\Temp\results.json'
with open(jsonFile, 'w') as dataFile:
json_obj = json.load(dataFile)
for i in json_obj["Summary"]:
print(i["fieldIWant"])
Not only am I not getting into the field I want, but I'm also getting a key error on trying to suss out "Summary".
I don't know how the indices work within the array; once I even get into the "Summary" field, do I have to issue an index manually to return the value from the field I need?
The example you posted is not valid JSON (no commas after object fields), so it's hard to dig in much. If it's straight from the web service, something's messed up. If you did fix it with proper commas, the "Summary" key is within the "Results" object, so you'd need to change your loop to
with open(jsonFile, 'w') as dataFile:
json_obj = json.load(dataFile)
for i in json_obj["Results"]["Summary"]:
print(i["fieldIWant"])
If you don't know the structure at all, you could look through the resulting object recursively:
def findfieldsiwant(obj, keyname="Summary", fieldname="fieldIWant"):
try:
for key,val in obj.items():
if key == keyname:
return [ d[fieldname] for d in val ]
else:
sub = findfieldsiwant(val)
if sub:
return sub
except AttributeError: #obj is not a dict
pass
#keyname not found
return None

Error handling in Python with JSON and a dictionary

I currently have a Python 2.7 script which scrapes Facebook and captures some JSON data from each page. The JSON data contains personal information. A sample of the JSON data is below:-
{
"id": "4",
"name": "Mark Zuckerberg",
"first_name": "Mark",
"last_name": "Zuckerberg",
"link": "http://www.facebook.com/zuck",
"username": "zuck",
"gender": "male",
"locale": "en_US"
}
The JSON values can vary from page to page. The above example lists all the possibles but sometimes, a value such as 'username' may not exist and I may encounter JSON data such as:-
{
"id": "6",
"name": "Billy Smith",
"first_name": "Billy",
"last_name": "Smith",
"gender": "male",
"locale": "en_US"
}
With this data, I want to populate a database table. As such, my code is as below:-
results_json = simplejson.loads(scraperwiki.scrape(profile_url))
for result in results_json:
profile = dict()
try:
profile['id'] = int(results_json['id'])
except:
profile['id'] = ""
try:
profile['name'] = results_json['name']
except:
profile['name'] = ""
try:
profile['first_name'] = results_json['first_name']
except:
profile['first_name'] = ""
try:
profile['last_name'] = results_json['last_name']
except:
profile['last_name'] = ""
try:
profile['link'] = results_json['link']
except:
profile['link'] = ""
try:
profile['username'] = results_json['username']
except:
profile['username'] = ""
try:
profile['gender'] = results_json['gender']
except:
profile['gender'] = ""
try:
profile['locale'] = results_json['locale']
except:
profile['locale'] = ""
The reason I have so many try/excepts is to account for when the key value doesn't exist on the webpage. Nonetheless, this seems to be a really clumpsy and messy way to handle this issue.
If I remove these try / exception clauses, should my scraper encounter a missing key, it returns a KeyError such as "KeyError: 'username'" and my script stops running.
Any suggestions on a much smarter and improved way to handle these errors so that, should a missing key be encountered, the script continues.
I've tried creating a list of the JSON values and looked to iterate through them with an IF clause but I just can't figure it out.
Use the .get() method instead:
>>> a = {'bar': 'eggs'}
>>> a['foo']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'foo'
>>> a.get('foo', 'default value')
'default value'
>>> a.get('bar', 'default value')
'eggs'
The .get() method returns the value for the requested key, or the default value if the key is missing.
Or you can create a new dict with empty strings for each key and use .update() on it:
profile = dict.fromkeys('id name first_name last_name link username gender locale'.split(), '')
profile.update(result)
dict.fromkeys() creates a dictionary with all keys you request set to a given default value ('' in the above example), then we use .update() to copy all keys and values from the result dictionary, replacing anything already there.

Categories