How to remove elements from JSON using Python - python

I receive the following data from an API request, I would like to be able to search the data and select the ID where Name = "Steve" (for instance 3 in the example below)
The data returned from the API always has a different number of elements in, and the location of 'Steve' can be in a different part of the returned string. The ID will also change.
(Getdata){
header =
(APIResponseHeader){
sessionToken = "xxxx"
}
Items[] =
(Summary){
Id = 1
Name = "John"
TypeId = 1
},
(Summary){
Id = 2
Name = "Jack"
TypeId = 1
},
(Summary){
Id = 3
Name = "Steve"
TypeId = 1
},
}
I think the format of the data is JSON(?) and I'm not sure how to convert, and then search it, if this is at all possible..?

Related

Trying to use Embedded Documents Fields in MongoDB

I'm following freecodecamp's video on MongoDB using mongoengine (as db). I'm trying to use the embedded document list field to add information to my main document. Also using a Streamlit webapp as my input source
My class's are:
class Contest(db.Document):
date_created = db.DateTimeField(default=datetime.today)
name = db.StringField(required=True)
format = db.EmbeddedDocumentField(Format)
class Format(db.EmbeddedDocument):
contest_id = db.ObjectIdField()
name = db.StringField()
Then I've tried a few different ways to to add the format to a specific contest instance.
Try #1
def set_format(active_contest):
format : Format = None
name = st.text_input('Name of Format:')
submit = st.button('Set Format Name')
if submit == True:
format.contest_id = active_contest.id
format.name = name
active_contest.save()
setting Format to None is the way the freecodecamp video shows... but i get this error: AttributeError: 'NoneType' object has no attribute 'contest_id'.
So I tried switching it to: format = Format()... this way it doesn't give me an error, but also doesn't update the Contest document to include the format information.
I also tried switching active_contest.save() to format.save() but then i get a: AttributeError: 'Format' object has no attribute 'save'
I've also tried the update function instead of save... but i get similar errors every-which way.
New to mongoDB and programming in general. Thanks in advance!
First of all, if you want to store Format as embedded document, the contest_id is not necessary in Format class. With this approach you will end with something like this in your MongoDB collection:
{
"date_created":ISODate(...),
"name": "...",
"format": {
"name": "..."
}
}
Another approach could be something like:
class Contest(db.Document):
date_created = db.DateTimeField(default=datetime.today)
name = db.StringField(required=True)
format = db.ReferenceField('Format') # <- Replaced by ReferenceField
class Format(db.Document): # <- EmbeddedDocument replaced by Document
name = db.StringField()
In that case each instance of "Format" will be stored in a separate collection. So you will end with something like this in MongoDB:
Collection Contest:
{
"date_created":ISODate(...),
"name": "...",
"format": :ObjectId("...") // <-- here's the relation field
}
Collection Format:
{
"_id":"...",
"name":"..",
}
Both approaches shares the same code:
def set_format(active_contest): # <-- here's the instance of 'Contest'
format : Format = Format() # <-- create a new Format instance
name = st.text_input('Name of Format:')
submit = st.button('Set Format Name')
if submit == True:
format.name = name
active_contest.format = format # <-- assigns the format to contest
active_contest.save() <- stores both because you are saving the 'parent' object

API call keeps giving keyerror? discord python

I have been trying to get this list of variables to work but it keeps giving me keyerror I have tried changing the variable etc but wont work
#client.command()
async def info(ctx):
url = ('https://randomuser.me/api/')
response = requests.get(url)
title = response.json()["title"]
first = response.json()["first"]
last = response.json()["last"]
number = response.json()["number"]
street = response.json()["name"]
city = response.json()["city"]
state = response.json()["state"]
postcode = response.json()["postcode"]
country = response.json()["country"]
phone = response.json()["phone"]
age = response.json()["age"]
dob = response.json()["date"]
gender = response.json()["gender"]
username = response.json()["username"]
password = response.json()["password"]
image = response.json()["large"]
embed = discord.Embed(title="Fake Info Generator", description=f"**Name:** '{title}', '{first}' '{last}'\n**Address:** '{number}' '{street}', '{city}', '{state}', '{postcode}', '{country}'\n**Phone:** '{phone}'\n**Age:** '{age}', '{dob}'\n**Gender:** '{gender}'", color=18321)
embed.set_footer(text="Random Info")
embed.set_image(url=f"'{image}'")
await ctx.send(embed=embed)
I have tried things like changing the variables to thing like this but still wont work
title = response.json()["name"][0]["title"]
Simply because that's now how JSON reading works.
You need to specify the entire "path" of the value you want to read. You can't just get response.json()["title"] because the response is not formatted like that.
The response JSON is formatted like the following:
{
"results":[
{
"gender":"female",
"name":{
"title":"Madame",
"first":"Germaine",
"last":"Rey"
},
...
}
],
...
}
To be able to read title you would need to read the content of the array results at index 0 (because you only care of the first result) then check the name and then finally the title, so it would look like that: response.json()["results"][0]["name"]["title"]

Passing multiple values from dictionary into method using loop

i have a question regarding adding dictionary key and value to method using loop
This is what i was thinking to write but it doesn't work how i want because it creates a packet just with one key/value every time
for key in packetData:
for name in packetData[key]:
packets = Ether()/IP()/UDP()/createsPacket(key, name=packetData[key][name])
print ("as name " + name + " \n as value " + str(packetData[key][name]))
Instead of writing this manually like that :
packets1 = Ether()/IP()/UDP()/createsPacket("65", UserID = "name", Password = "pass123", ETX = 123)
packets2 = Ether()/IP()/UDP()/createsPacket("72", PriceID = 123, Side = 12, MaxAmount = 123, MinAmount = 123, Price = 123000)
    json then converted to dictionary in python , this is data that i want to pass in
{
"65":{
"UserID":"vcjazfan",
"Password":"ejujwlhk",
"SessionID":115,
"ETX":192
},
"66":{
"UserID":"dzmtrssy",
"SessionID":35,
"Reason":"zbwivjcv",
"ETX":43
},
"72":{
"InstrumentIndex":171,
"PriceID":217,
"Side":226,
"MaxAmount":210,
"MinAmount":219,
"Price":47,
"PriceProvider":207,
"ETX":78
},
Made more generic for easier understanding, hoping it helps
Generic code
dictionary = {"65":{ "UserID":"vcjazfan", "Password":"ejujwlhk", "ETX":192} , "72":{ "InstrumentIndex":171, "PriceID":217, } }
#This is what i was thinking to write but it doesn't work how i want because it creates a packet just with one key/value every time
for key in dictionary:
for name in dictionary[key]:
value=dictionary[key][name]
packets = method(key, name=value) # in first iteration when key is 65 , name = "UserID" , value = "vcjazfan"
# in second iteration when key is 65 , name = "Password" , value = "ejujwlhk"
#Instead of writing this manually like that :
packets1 = method("65", UserID = "name", Password = "pass123", ETX = 123)
packets2 = method("72", InstrumentIndex = 123, PriceID = 12,)
This question solved my problem : How to pass dictionary items as function arguments in python?
solution to my original code:
Allpackets= []
for key in packetData:
Allpackets.append(packets/createsPacket(key, **packetData[key]))
Solution to generic one:
dictionary = {"65":{ "UserID":"vcjazfan", "Password":"ejujwlhk", "ETX":192} , "72":{ "InstrumentIndex":171, "PriceID":217, } }
Allpackets = []
for key in dictionary:
Allpackets.append( method(key, **dictionary))
#Instead of writing this manually like that :
packets1 = method("65", UserID = "name", Password = "pass123", ETX = 123)
packets2 = method("72", InstrumentIndex = 123, PriceID = 12,)

Looping over Protocol Buffers attributes in Python

I would like help with recursively looping over all attributes/sub objects contained in a protocol buffers message, assuming that we do not know the names of them, or how many there are.
As an example, take the following .proto file from the tutorial on the google website:
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
and to use it...:
person = tutorial.Person()
person.id = 1234
person.name = "John Doe"
person.email = "jdoe#example.com"
phone = person.phone.add()
phone.number = "555-4321"
phone.type = tutorial.Person.HOME
Given Person, How do I then access both the name of the attribute and its value for each element: person.id, person.name, person.email, person.phone.number, person.phone.type?
I have tried the following, however it doesn't seem to recurs into person.phone.number or person.phone.type.
object_of_interest = Person
while( hasattr(object_of_interest, "_fields") ):
for obj in object_of_interest._fields:
# Do_something_with_object(obj) # eg print obj.name
object_of_interest = obj
I have tried using obj.DESCRIPTOR.fields_by_name.keys to access the sub elements, but these are the string representations of the sub objects, not the objects themselves.
obj.name gives me the attribute of the name, but im not sure how to actually get the value of that attribute, eg obj.name may give me 'name', but how do i get 'john doe' out of it?
I'm not super familiar with protobufs, so there may well be an easier way or api for this kind of thing. However, below shows an example of how you could iterate/introspect and objects fields and print them out. Hopefully enough to get you going in the right direction at least...
import addressbook_pb2 as addressbook
person = addressbook.Person(id=1234, name="John Doe", email="foo#example.com")
person.phone.add(number="1234567890")
def dump_object(obj):
for descriptor in obj.DESCRIPTOR.fields:
value = getattr(obj, descriptor.name)
if descriptor.type == descriptor.TYPE_MESSAGE:
if descriptor.label == descriptor.LABEL_REPEATED:
map(dump_object, value)
else:
dump_object(value)
elif descriptor.type == descriptor.TYPE_ENUM:
enum_name = descriptor.enum_type.values[value].name
print "%s: %s" % (descriptor.full_name, enum_name)
else:
print "%s: %s" % (descriptor.full_name, value)
dump_object(person)
which outputs
tutorial.Person.name: John Doe
tutorial.Person.id: 1234
tutorial.Person.email: foo#example.com
tutorial.Person.PhoneNumber.number: 1234567890
tutorial.Person.PhoneNumber.type: HOME

Format this data as XML or JSON with Python

I have a SOAP web service that I am posting a request to with Python, but I am not sure how to format the return.
UPDATE: Return is an 'instance' being returned by SUDS
I have been able to return just one record of the 40, which is included below:
print len(xmloutput)
print len(xmloutput[1].ODI_Outage)
print xmloutput[1].ODI_Outage[6]
This is the return that I am getting:
2
40
(ODI_Outage){
metersAffected = 28
ERT =
(ert_time){
ert = "2013-07-19T20:50:00Z"
}
Incident =
(incident){
Location =
(location){
mainAddress =
(mailaddress){
townDetail =
(towninfo){
code = "L7L6W3"
name = "BURLINGTON"
stateOrProvince = "ONTARIO"
}
}
PositionPoints =
(coordinates){
xPosition = -79.7833492971
yPosition = 43.3923166879
}
}
}
}
How do I take this return and create either XML or JSON for all of the ODI_Outage objects? Just not sure what to do.
To check the type of the return use: print type(your_return_variable)

Categories