How to convert an string with array form to an array? - python

I got a string in this form
payload = ["Text 1", "Text 2"]
I want to use Text 2 as an object. How can I return it?
UPDATE
I'm making a function which returns a generic template Facebook API.
The first payload works well, but I want to return a string and a object in the second payload ( result )
button = [
{
"type": "postback",
"title": "Buy item",
"payload": "Buy this item: " + (product['id'])
},
{
"type": "postback",
"title": "Add to wishlist",
"payload": result
}
]
My second payload should look like this:
payload = {
'Order_item',
product['title']
}
Because I got this error [buttons][1][payload] must be a UTF-8 encoded string so I did convert it and it returns a STRING in this form ["Order_item", "Ledverlichting Fiets Blauw"]
Because I want that when a Facebook user clicks on a postback ( Add to wishlist ), the product['title'] value will be save in Django database. And product['title'] is the Text 2 in the question above.

You need to split the string then trim and keep splitting/trimming to get all parts that you want to have in list
s = 'payload = ["Text 1", "Text 2"]'
items = s.strip()[1:-1]
#if 'payload = ' is also part of string you need to split it also by '=' so it would be:
#items = s.split("=").strip()[1:-1]
l = [item.strip()[1:-1] for item in items.split(",")]
then you have list of string that you can iterate, get n-th item and so on
the_item = l[1]
return the_item

assuming that you want a string object, you can get the specific index in the array(first spot = 0, second spot = 1, etc).
you can save the string object contained in the array like this:
payload = ["Text 1", "Text 2"]
s = payload[1]
and than you can return the s object.

you can try:
>>> payload = ["t1", "t2"]
>>> t2 = [1,2]
>>> eval(payload[1])
[1, 2]

I had a string that was in strictly list format and simply passing it through eval() worked.

Related

Generating specific fields from JSON objects

I have a rather massive JSON objects and I'm trying to generate a specific JSON using only certain elements from it.
My current code looks like this:
data = get.req("/v2/users")
data = json.loads(data)
print (type(data)) # This returns <class 'list'>
print (data) # Below for what this returns
all_data = []
for d in data:
login_value = d['login']
if login_value.startswith('fe'):
continue
s = get.req("/v2/users/" + str(login_value)) # Sending another request with each
# login from the first request
all_data.append(s)
print (all_data) # Below for what this looks like this
print (data) before json.loads is str for the information, it returns data like this:
[
{
"id": 68663,
"login": "test1",
"url": "https://x.com/test"
},
{
"id": 67344,
"login": "test2",
"url": "https://x.com/test"
},
{
"id": 66095,
"login": "hi",
"url": "https://x.com/test"
}
]
print (all_data) returns a similar result to this for every user a request was sent for the first time
[b'{"id":68663,"email":"x#gmail.com","login":"xg","phone":"hidden","fullname":"xg gx","image_url":"https://imgur.com/random.png","mod":false,"points":5,"activity":0,"groups":['skill': 'archery']}
And this repeats for every user.
What I'm attempting to do is filtering by a few fields from all those results I received, so the final JSON I have will look something like this
[
{
"email": "x#gmail.com",
"fullname": "xg gf",
"points": 5,
"image_url", "https://imgur.com/random.pmg"
},
{
... similar json for the next user and so on
}
]
I feel as if the way I'm iterating over the data might be inefficient, so if you could guide me to a better way it would be wonderful.
In order for you to fetch login value, you have to iterate over data atleast once and for fetching details for every user, you have to make one call and that is exactly what you have done.
After you receive the user details instead of appending the whole object to the all_data list just take the field you need and construct a dict of it and then append it to all_data.
So your code has time complexity of O(n) which is best I understand.
Edit :
For each user you are receiving a byte response like below.
byte_response = [ b'{"id":68663,"email":"x#gmail.com","login":"xg","phone":"hidden","fullname":"xg gx","image_url":"https://imgur.com/random.png","mod":false,"points":5,"activity":0,"groups":[]}']
I'm not sure why would you get a response in a list [], but if it like that then take byte_response[0] so that we have the actual byte data like below.
byte_response = b'{"id":68663,"email":"x#gmail.com","login":"xg","phone":"hidden","fullname":"xg gx","image_url":"https://imgur.com/random.png","mod":false,"points":5,"activity":0,"groups":[]}'
response_decoded = byte_response.decode("utf-8") #decode it
import json
json_object_in_dict_form = json.loads(response_decoded) #convert it into dictionary
and then...
json_object_in_dict_form['take the field u want']
you can write:
data = get.req("/v2/users")
data = json.loads(data)
all_data = []
for d in data:
...
s = get.req("/v2/users/" + str(login_value))
new_data = {
'email': s['email'],
'fullname': s['fullname'],
'points': s['points'],
'image_url': s['image_url']
}
all_data.append(new_data)
print (all_data)
or you can make it fancy using an array with the fields you need:
data = get.req("/v2/users")
data = json.loads(data)
all_data = []
fields = ['email', 'fullname', 'point', 'image_url']
for d in data:
...
s = get.req("/v2/users/" + str(login_value))
new_data = dict()
for field in fields:
new_data[field] = s[field]
all_data.append(new_data)
print (all_data)

How to bulk update a field in elasticsearch?

def update(index):
index = "twitter"
list = ['0oPwSm4BxbPrifDrF7C1', 'r4MOWm4BxbPrifDrjbgR', 'y4NbWm4BxbPrifDrLLhh']
data = []
for i in list:
d = { "update" : {"_id" : i, "_index" : index, "retry_on_conflict" : 3} }
e = { "doc" : {"answer_1" : "test"} }
data.append(json.dumps(d))
data.append(json.dumps(e))
v = "\n".join(data)
response = requests.post('https://url/_bulk', headers='application/x-ndjson',
data=json.loads(v)
I want to bulk update the answer field for different documents. Unable to send request in a proper format i guess.
The bulk data set should be like this,
{'index': ''}\n
{'your': 'data'}\n
{'index': ''}\n
{'other': 'data'}\n
NB: the new-lines, even on the last row.
Your existing data seems OK to me,
{"update": {"_id": "0oPwSm4BxbPrifDrF7C1", "retry_on_conflict": 3, "_index": "twitter"}}
{"doc": {"answer_1": "test"}}
{"update": {"_id": "r4MOWm4BxbPrifDrjbgR", "retry_on_conflict": 3, "_index": "twitter"}}
{"doc": {"answer_1": "test"}}
{"update": {"_id": "y4NbWm4BxbPrifDrLLhh", "retry_on_conflict": 3, "_index": "twitter"}}
{"doc": {"answer_1": "test"}}
You have got a syntax error on the request.post() where you missed ending parenthesis ) and need to send v directly without using extra json.loads(v)
response = requests.post('https://url/_bulk',
data=v,
headers={'content-type':'application/json',
'charset':'UTF-8'})
print(response)
This seems to be the problem
data=json.loads(v)
'v' does not contain a parsable json string, it contains multiple JSON documents seperated by new lines. Try sending v directly without parsing.

How to output formatted text from list of values from JSON?

I am working on a slackbot. I have a json file and python code that outputs something to slack based on the user's input. There is a search command that outputs search results from a json file. The current output is not formatted because when the values are taken from the json, they are appended to a list and then returned to the main python program.
I have tried creating a loop that would kind of parse through the search output and cut it down so that each set of values are separate and then added to a list that can be formatted. The loop I tried doesn't really work, and I'm not too sure how to properly make a loop that I can use to format the output. I have also tried formatting the output using format(), but it doesn't work because it is a list.
This is the an example of the current search output.
if command.startswith(SEARCH):
try:
search = search_data(command.split(' ')[1])
response = search
except KeyError:
response = 'This search key does not exist.'
except TypeError:
response = 'Wrong search input'
This is an example search command that I import from another python script:
def search_data(keyword):
result = []
for key, value in data.items():
first = value['first']
last = value['last']
if keyword in first:
result.append(value)
elif keyword in last:
result.append(value)
return result
This is an example JSON:
{
"1": {
"id": "1",
"first": "Joe",
"last": "Adam"
},
"2": {
"id": "2",
"first": "Mary",
"last": "Smith"
},
"3": {
"id": "3",
"first": "Ann",
"last": "John"
}
}
I have another output which I format using this line of code and I want to format my list output the same way.
response = '*ID:* {}\n *First:* {}\n *Last:*
{}\n\n'.format(search['id'],search['first'],search['last'])
The expected output is for the user to enter a search in slack using the slackbot. The user can input "search J" for example and the output lists the matching set of values that have a J in either the "first" or "last" values. My current output is something like:
[{"id":"1","first":"Joe","last":"Adam"},
{"id":"2","first":"Ann","last":"John"}]
but I want to format it like:
ID: 1
First: Joe
Last: Adam
ID: 2
First: Ann
Last: John
this should do it
"\n\n".join([f"ID: {out['id']}\nFirst: {out['first']}\nLast: {out['last']}" for out in result])

Python creating a string using \ and send it in a json request

I am trying to automate some queries to a API using Python. The problem is that the request needs to be created in a special way, and I just cant make it work. This is the part of the string I am having problems creating.
payload = "{\n \"filter\": {\n \"name\":[\"name1\", \"name2\"]\n }"
Where name1 and name2 is variable and is created from a list. The way I tried to do it was just to first create a function to create the
[\"name1\", \"name2\"]
This is the function
def create_string(list_of_names):
#Creates the string of line items we want data from
start = '[\\"%s\\"' % list_of_names[0]
for i in list_of_names[1 : ]:
start += ', \\"%s\\"' %(i)
start += "]"
return start
list_of_names = ['name1', 'name2']
And then just using the %s part to add it into the string.
payload = "{\n \"filter\": {\n \"name\":%s\n }" % create_string(list_of_names)
This doesnt work, and I can think this has something to do with how the \ is used in Python.
The create_string function creates different output depening on if I am printing it or not.
a = create_string(list_of_names)
print(a)
Creates the string I need to pass in using %s
[\"name1\", \"name2\", \"name3\"]
And just a outputs
'[\\"name1\\", \\"name2\\", \\"name3\\"]'
So my problem is then how to pass the print(a) part into the payload string. Does anyone have some sort of solution to this?
Instead of creating your payload by hand, first create a python dictionary and use the json-module to convert it to a string:
payload = {"filter": {"name": list_of_names]}}
payload = json.dumps(payload)
or with your more complex dictionary:
payload = {
"filter": {
"date": "pastThirtyDays",
"lineitem": {
"buyType": "RTB",
"name": list_of_names,
}
},
"metrics": ["cost"],
"dimensions": ["date", "lineItem"],
}
payload = json.dumps(payload)

Create Dynamic Python Dictionary Reference Path

I'm having trouble dynamically creating a Python dictionary path to loop through and validate a value. Here's what I'd like to do:
Make API call using Requests 1.0 and store the JSON response in a dict.
response = requests.get(path/to/file.json).json()
The response object will be formatted as follows:
{
"status": "OK",
"items": [
{
"name": "Name 1",
"id": 0,
"address":{
"city": "New York",
}
},
{
"name": "Name 2",
"id": 1,
"address":{
"city": "New York",
}
},
{
"name": "Name 3",
"id": 2,
"address":{
"city": "New York",
}
}]
}
Send the response dict, field and value to a function for validation. The function would take the response object and append the field entry to it to define its path then validate against the value. So in theory it would be:
response[field] = value
The code that I wrote to do this was:
def dynamic_assertion(response, field, value):
i = 0
stations = "response['items']"
count = len(response['items'])
while i < count:
path = '%s[%s]%s' % (stations, i, field)
path = path.strip("")
if path != value:
print type(path)
return False
i += 1
return True
dynamic_assertion(response, "['address']['city']", "New York")
I realize that once I create the path string it is no longer an object. How do I create this in a way that will allow me to keep the response object and append the reference path to traverse through? Is this even possible?!
I think you'd be better off avoiding a single path string in favor of a tuple or list of strings which represent the individual keys in the nested dictionaries. That is, rather than "['address']['city']" being your field argument, you'd pass ("address", "city"). Then you just need a loop to go through the keys and see if the final value is the correct one:
def dynamic_assertion(response, field, value):
for item in response["items"]:
for key in field:
item = item[key] # go deeper into the nested dictionary
if item != value:
return False # raising an exception might be more Pythonic
return True
Example output (given the response dict from the question):
>>> dynamic_assertion(response, ("address", "city"), "New York")
True
>>> dynamic_assertion(response, ("address", "city"), "Boston")
False
>>> response["items"][2]["address"]["city"] = "Boston" # make response invalid
>>> dynamic_assertion(response, ("address", "city"), "New York")
False
>>> dynamic_assertion(response, ("address", "city"), "Boston")
False

Categories

Resources