Accessing values from Rest API JSON output - python-3.x

I'm trying to access certain values from returned rest API output. I have converted to a dictionary and now I'm trying to access elements from the list, starting from "list": [
rest_response = {
"total": 2,
"offset": 0,
"limit": 25,
"list": [
{"id": 2233,
"url": "/v1/test/v2",
"enabled": true,
"info": {
"reason": "N/A",
"policy_name": "test",
"statuschk_tm": "2020-09-07 07:00:01",
"lock": "1",
"TYPE": "1"
}
]
}
Previously I've been able to write a for loop a to search for values in the list, as below.
rest_response = rest_response['list']
for info in rest_response:
id = info['id']
print(id)
However, if I use a similar for loop to search for value that start after "info": { then I get a key error.
rest_response = rest_response['info']
for info in rest_response:
name = info['policy_name']
print(name)
I have viewed related posts but when I attempt to access I get "TypeError: list indices must be integers or slices, not str"
Python Accessing Nested JSON Data
Having trouble with nested Python3 dictionary
Any ideas on what I can do to view values from "info": onwards?

Info is a dictionary in itself which contains policy-name which you cannot access directly. So you have to nest accordingly. This should work:
for x in rest_response:
info = x['info']
print(info['policy_name'])

For accessing info dictionary you have to use the following code snippet -
rest_response['list'][0]['info']['policy_name']

Related

MAP Nested JSON using rest API in Azure Data Factory using for each Iterator through a stored procedure to a SQL table

I am pulling a list of pipeline using REST API in ADF. The API gives a nested JSON and I am using a for each iterator to be pulled via a stored procedure to be pulled into a SQL table.
The sample JSON looks like this:
{
"value": [
{
"id": "ADF/pipelines/v_my_data_ww",
"name": "v_my_data_ww",
"type": "MS.DF/factories/pipelines",
"properties": {
"activities": [
{
"name": "Loaddata_v_my_data_ww",
"type": "Copy",
"dependsOn": [],
"policy": {
"timeout": "7.00:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
}
]
},
"folder": {
"name": "myData"
},
"annotations": [],
"lastPublishTime": "2021-04-01T22:09:20Z"
,
"etag": "iaui7881919"
}
}
]
}
So using the For Each Iterator #activity('Web1').output.value, I was able to pull in the main keys, like id, name , type. However I also need to pull in the name/type from within the properties/activities tag. not sure how to do it. I was trying the following.
When I run the pipeline, I get the following error:
The expression 'item().properties.activities.name' cannot be evaluated because property 'name' cannot be selected. Array elements can only be selected using an integer index.
Any help in this regards will be immensely appreciated.
The error is because you are trying to access an array i.e., activities directly with a key. We need to access array elements with indices such as activities[0]
The following is a demonstration of how you can solve this. I got the same error when I used #item().properties.activities.name.
To demonstrate how to solve this, I have taken the given sample json as a parameter for pipeline and passing #pipeline().parameters.js.value in for each activity.
Now, I have used a set variable to show how I retrieved the name and type present in the activities property. The following dynamic content helps in achieving this.
#item().properties.activities[0].name
So, modify your prop_name and prop_type to the following dynamic content:
#item().properties.activities[0].name
#item().properties.activities[0].type
UPDATE:
If there are multiple objects inside activities property array, then you can follow the procedure below:
Create an execute pipeline activity to execute a pipeline called loop_activities. Create 4 parameters in loop_activities pipeline name, id, tp, activities. Pass the dynamic content as shown below:
In loop_activities pipeline, use for each to iterate through activities array. The dynamic content value for items field is #pipeline().parameters.activities.
Inside for each, you can access each required element with following dynamic content.
#for name:
#pipeline().parameters.name
#for id:
#pipeline().parameters.id
#for type:
#pipeline().parameters.type
#for prop_name:
#item().name
#for prop_type:
#item().type
The following is debug output of loop_activities (only for prop_name and prop_type) when I run pipeline1.

Python: how to replace by blank or NA as exception in a list of properties?

I tried google some hours without solution.
So created this account try to ask by myself.
I am using python to generate a user list and export as csv.
I can print(Users['Id'],Users['Name']) without error as all users have these two fields.
But if I print(Users['Id'],Users['Name'],Users['Email']),
I met errors, if I write try and exception as pass, I got only one user result S3 alex as only alex has the field Email.
May I know if there is a way that I can put all the 6 field names as the table header.
Then whenever a user has no value on any fields, just put NA or leave it blank ? Thanks.
My code looks like this:
fo=open('Userlist.csv','w',newline='')
data_obj=csv.writer(fo)
data_obj.writerow(['cnt','Name','Id'])
cnt=1
result = get_users()
for user in result['Users']:
print(user['Name'],user['Id']) # to see result
data_obj.writerow([user['Name'],user['Id']]) # to write data into csv rows
row_number += 1
fo.close()
#If I print(result), get below result with different fields:
"Users": [
{
"Id": "S-1xxxx",
"Name": "S1 Peter",
"State": "DISABLED",
"UserRole": "USER"
},
{
"Id": "S-2xxxx",
"Name": "S2 Mary",
"State": "DISABLED",
"UserRole": "USER"
},
{
"Id": "S-3xxxx",
"Email": "alex#domain.com",
"Name": "S3 alex",
"State": "ENABLED",
"UserRole": "USER",
"EnabledDate": "2020-1-5"
},
{
"Id": "S-4xxxx",
"Name": "S3 brand",
"State": "DELETED",
}]
[expected result][1]
[1]: https://i.stack.imgur.com/fIMMB.png
with open("Userlist.csv", "w") as f:
w = csv.writer(f)
w.writerow(["Id", "Name", "Email"])
for user in users:
w.writerow([user.get("Id"), user.get("Name"), user.get("Email")])
The with keyword causes python to use a context manager and means you don't need to worry about closing your file. It's not vital to this solution, but it's good practice.
Using get() looks for your key and returns None if it doesn't exist, thus not throwing an error if it doesn't.

How do you check if any objects in an array has a property with value in Azure Logic App?

I am building a Azure Logic App which recieves a webhook. I need to parse the body and validate if a array contains any object with a property that matches either of two values, but have no idea how to do it.
Any ideas?
The JSON i am recieving in the webhook is like below, shortened for brevity. I am looking at the components-array:
{
"id": "12601",
"components": [
{
"id": "10021",
"name": "Value1"
},
{
"id": "10022",
"name": "Value2"
},
{
"id": "10023",
"name": "Value3"
}
]
}
From this array I need to output a parameter true/false if any properties with name == "Value1" or "Value" appears.
Is there any syntax similar to LINQ in C#, or do you use a foreach? I have not been able to find any simple way like:
If(Arr.Any(x => x.name == "Value1"))
Perhaps you can use Parse Json to parse the Json string you received, and then use condition to determine whether the name contains value1.
Please refer to my logic app:

List iteration on python with mongodb

I am working on a small python project where I need to create a mongodb entry.
This is the list of values you received from another collection:
["India", "Australia", "South Africa"]
So the above list contains three items. What I want from my next collection is:
{
"_id": ObjectId('some id'),
"name": "Player",
"value": "India"
}
{
"_id": ObjectId('some id'),
"name": "Player",
"value": "Australia"
}
{
"_id": ObjectId('some id'),
"name": "Player",
"value": "South Africa"
}
I only want the list of values to be added in the value key but the name should be constant. It should repeat again and again but the value key will be changed based on number entries in the list.
How do I approach this problem in python?
You can apparoch this issue in different ways. A very basic one would be using list comprehensions like this:
values_list = ["India", "Australia", "South Africa"]
names_list = ["Peter", "Paul", "Mary"]
def create_objects(name, values):
# this returns a list of dicts basically and should be adopted to create 'real' mongoDB objects/entries
return [{"_id": "some id", "name": name, "value": value} for value in values]
objects = [create_objects(name, values_list) for name in names_list]
print(objects)
Another way is to calculate all possible combinations (called product in itertools) before-hand to prevent the two interating for-loops
from itertools import product
objects = [{"_id": "some id", "name": name, "value": value} for name, value in product(names_list, values_list)]
print(objects)

Access a dictionary value based on the list of keys

I have a nested dictionary with keys and values as shown below.
j = {
"app": {
"id": 0,
"status": "valid",
"Garden": {
"Flowers":
{
"id": "1",
"state": "fresh"
},
"Soil":
{
"id": "2",
"state": "stale"
}
},
"BackYard":
{
"Grass":
{
"id": "3",
"state": "dry"
},
"Soil":
{
"id": "4",
"state": "stale"
}
}
}
}
Currently, I have a python method which returns me the route based on keys to get to a 'value'. For example, if I want to access the "1" value, the python method will return me a list of string with the route of the keys to get to "1". Thus it would return me, ["app","Garden", "Flowers"]
I am designing a service using flask and I want to be able to return a json output such as the following based on the route of the keys. Thus, I would return an output such as below.
{
"id": "1",
"state": "fresh"
}
The Problem:
I am unsure on how to output the result as shown above as I will need to parse the dictionary "j" in order to build it?
I tried something as the following.
def build_dictionary(key_chain):
d_temp = list(d.keys())[0]
...unsure on how to
#Here key_chain contains the ["app","Garden", "Flowers"] sent to from the method which parses the dictionary to store the key route to the value, in this case "1".
Can someone please help me to build the dictionary which I would send to the jsonify method. Any help would be appreciated.
Hope this is what you are asking:
def build_dictionary(key_chain, j):
for k in key_chain:
j = j.get(k)
return j
kchain = ["app","Garden", "Flowers"]
>>> build_dictionary(kchain, j)
{'id': '1', 'state': 'fresh'}

Resources