Access a dictionary value based on the list of keys - python-3.x

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'}

Related

How to extract two value from json under one condition and randomize it in jmeter?

Below is the server response in a JSON format which I need to work on, In this JSON some of the objects I need to pass in the next request, which I am successfully able to do for the first occurrence, but the problem is coming on randomization in the below JSON
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sword of Honour",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "test_title",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Sword of Honour",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "India",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
if I apply $..book[0][?(#.title == 'Sword of Honour')] condition I am seeing successful output
test_1={"category":"reference","title":"Sword of Honour","author":"Nigel Rees","price":8.95}
test_2={"category":"fiction","title":"Sword of Honour","author":"Herman Melville","price":8.99,"isbn":"0-553-21311-3"}
if I apply $..book[0][?(#.title == 'Sword of Honour')].author condition I am seeing successful output
test_1=Nigel Rees
test_2=Herman Melville
But I want to extract both author's name and price for the book that has the title == 'Sword of Honour'
Actual output = able to retrieve one value with the condition $..book[0][?(#.title == 'Sword of Honour')].author
Expected output = I want to receive two values from the same list randomly. and it should look like this
Iteration 1-
test_1={"author":"Nigel Rees","price":8.95}
Iteration 2-
test_2={"author":"Herman Melville","price":8.99,}
Iteration 3-
test_2={"author":"Herman Melville","price":8.99,}
I had tried with the V function as well but got only one value. (book{__V([?(#.title == 'Sword of Honour')]_${__Random(1,${title_matchNr},)},)})
Add JSR223 PostProcessor as a child of the request which returns the above JSON
Put the following code into "Script" area:
def swords = new groovy.json.JsonSlurper().parse(prev.getResponseData()).store.book.findAll { book -> book.title == 'Sword of Honour' }
swords.eachWithIndex { def sword, int index ->
def payload = [:]
payload.put('author', sword.author)
payload.put('price', sword.price)
vars.put('test_' + (index + 1), new groovy.json.JsonBuilder(payload).toPrettyString())
}
vars.put('test_matchNr', swords.size() as String)
Now you should be able to refer random author/price pair using __V() and __Random() functions combination like: ${__V(test_${__Random(1,${test_matchNr},)},)}
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy: What Is Groovy Used For?

How to extract selected key and value from nested dictionary object in a list?

I have a list example_list contains two dict objects, it looks like this:
[
{
"Meta": {
"ID": "1234567",
"XXX": "XXX"
},
"bbb": {
"ccc": {
"ddd": {
"eee": {
"fff": {
"xxxxxx": "xxxxx"
},
"www": [
{
"categories": {
"ppp": [
{
"content": {
"name": "apple",
"price": "0.111"
},
"xxx: "xxx"
}
]
},
"date": "A2020-01-01"
}
]
}
}
}
}
},
{
"Meta": {
"ID": "78945612",
"XXX": "XXX"
},
"bbb": {
"ccc": {
"ddd": {
"eee": {
"fff": {
"xxxxxx": "xxxxx"
},
"www": [
{
"categories": {
"ppp": [
{
"content": {
"name": "banana",
"price": "12.599"
},
"xxx: "xxx"
}
]
},
"date": "A2020-01-01"
}
]
}
}
}
}
}
]
now I want to filter the items and only keep "ID": "xxx" and the correspoding value for "price": "0.111", expected result can be something similar to :
[{"ID": "1234567", "price": "0.111"}, {"ID": "78945612", "price": "12.599"}]
or something like {"1234567":"0.111", "78945612":"12.599" }
Here's what I've tried:
map_list=[]
map_dict={}
for item in example_list:
#get 'ID' for each item in 'meta'
map_dict['ID'] = item['meta']['ID']
# get 'price'
data_list = item['bbb']['ccc']['ddd']['www']
for data in data_list:
for dataitem in data['categories']['ppp']
map_dict['price'] = item["content"]["price"]
map_list.append(map_dict)
print(map_list)
The result for this doesn't look right, feels like the item isn't iterating properly, it gives me result:
[{"ID": "78945612", "price": "12.599"}, {"ID": "78945612", "price": "12.599"}]
It gave me duplicated result for the second ID but where is the first ID?
Can someone take a look for me please, thanks.
Update:
From some comments from another question, I understand the reason for the output keeps been overwritten is because the key name in the dict is always the same, but I'm not sure how to fix this because the key and value needs to be extracted from different level of for loops, any help would be appreciated, thanks.
as #Scott Hunter has mentioned, you need to create a new map_dict everytime you are trying to do this. Here is a quick fix to your solution (I am sadly not able to test it right now, but it seems right to me).
map_list=[]
for item in example_list:
# get 'price'
data_list = item['bbb']['ccc']['ddd']['www']
for data in data_list:
for dataitem in data['categories']['ppp']:
map_dict={}
map_dict['ID'] = item['meta']['ID']
map_dict['price'] = item["content"]["price"]
map_list.append(map_dict)
print(map_list)
But what are you doing here is that you are basically just "forcing" your way through ... I recommend you to take a break and check out somekind of tutorial, which will help you to understand how it really works in the back-end. This is how I would have written it:
list_dicts = []
for example in example_list:
for www in item['bbb']['ccc']['ddd']['www']:
for www_item in www:
list_dicts.append({
'ID': item['meta']['ID'],
'price': www_item["content"]["price"]
})
Good luck with this problem and hope it helps :)
You need to create a new dictionary for map_dict for each ID.

Accessing values from Rest API JSON output

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']

How to parse json when you have 'dynamic' values

Thanks for taking the time out to read this. I want to find a way of parsing the json below. I'm really struggling to get the correct values out. I am getting this info from an API, and want to save this data into a database.
I am really struggling to parse info_per_type because I first need to get the available_types. This can change depending on the info available (i.e. I might get 2 different types in the next call, there's a total of 4) so my code needs to be flexible enough to deal with this
```
{
"data": [
{
"home_team": "Ravenna",
"id": 82676,
"available_types": [
"type_a",
"type_b"
],
"info_per_type": {
"type_a": {
"options": {
"X": 0.302,
"X2": 0.61,
"X3": 0.692,
"X4": 0.698,
"X5": 0.39,
"X6": 0.308
},
"status": "pending",
"output": "12",
"option_values": {
"X": 3.026,
"X2": 1.347,
"X3": 1.516,
"X4": 1.316,
"X5": 2.936,
"X6": 2.339
}
},
"type_b": {
"options": {
"yes": 0.428,
"no": 0.572
},
"status": "pending",
"output": "no",
"option_values": {
"yes": null,
"no": null
}
}
}
}
]
}```
So far, I can get the available_types out. But after that, I'm stuck. I have tried eval and exec but I can't seem to get that working either.
```
r = requests.get(url, headers=headers).text
arrDetails = json.loads(r)
arrDetails = arrDetails['data']
x = arrDetails[0]['available_types']
print(x[1]) #I get the correct value here
y = exec("y = arrDetails[0]['info_per_type']['" + x[1] + "']")
print(y)```
When I print out y I get None. What I want is some way to reference that part of the json file, as the results within that node are what I need. Any help would be HIGHLY appreciated!
Something like this should work :
for row in arrDetails['data']:
for available_type in row['available_types']:
print(row['info_per_type'][available_type])

How to get the position of an object in an array?

I'm trying to get the position in array of the first object so i can delete it with a function. The problem is: i don't know how to get the "index"value.
{
"2": {
"nome": "sou1",
"email": "adsa#lala.com",
"gênero": "masculino",
"id": 1,
"pos": 0
},
"3": {
"nome": "sou1",
"email": "adsa#lala.com",
"gênero": "masculino",
"id": 1,
"pos": 1
}
}
In this case, my output would be 2.
You can try the below
var someObject={
"2": {
"nome": "sou1",
"email": "adsa#lala.com",
"gênero": "masculino",
"id": 1,
"pos": 0
},
"3": {
"nome": "sou1",
"email": "adsa#lala.com",
"gênero": "masculino",
"id": 1,
"pos": 1
}};
console.log(Object.keys(someObject)[0]);
delete someObject[Object.keys(someObject)[0]];
console.log(someObject);
There is no ordering in JSON objects.
However, for your use case (if I correctly understand that), you can convert the JSON object into an array doing...
const someObject = {
a: "A",
b: "B",
c: "C"
}
const keys = Object.keys(someObject);
console.log(keys); // array of keys
let arr = [];
for(key of keys) {
arr.push(someObject[key]);
}
console.log(arr); // array of objects
...where the index of an element in the keys array (a key in your original JSON object) will be identical to the index of an element in the arr array (the corresponding value for that key in your original JSON object) which it maps to in your original JSON object, in a way giving you what you probably are looking for. Then you can access them using the array indices.
Hope this helps :)

Resources