How to grab dict value from string of square bracket notation - python

Let's say I have the dictionary my_dict:
my_dict = {"vms": {"vm": {"name": "test-vm", "desc": "test"}}}
Obviously, in code I can grab the VM data with:
my_dict['vms']['vm']
More to the point, I can create an object of vms with that value and then reference the data:
vms = my_dict['vms']
vm = vms['vm']
My question is, if I were to save the value vms['vm'] as a string in a configuration file, how can I then use said string to grab the value from the dictionary? Something like:
my_dict.grab("vms['vm']") # To grab my_dict['vms']['vm']
I'm hoping a solution that I can further use with, say, vms['vm']['name'] regardless of how nested it gets, akin to Ansible Facts in a YAML playbook:
my_dict.grab("vms['vm']['name']")

So it turns out what I was looking for was Jinja2
from jinja2 import Template
my_dict = {"vms": {"vm": {"name": "test-vm", "desc": "test"}}}
string_location = "{{ vms['vm'] }}"
print(Template(string_location).render(my_dict))

Related

How to Identify an dictionary inside an dictionary

I have a dictionary like this:
test = {'user_id':125, 'company':'XXXX', 'payload': {"tranx": "456b62448367","payload": {"snr": "25%","Soil": 45,"humidity": 85}}}
The requirement is :
the payload inside a dictionary(test), is dynamic sometimes the payload will come and sometimes it won't, and the payload name is temporary, may after some time it will become "abc" or anything.
In this case,
I want to Identify the "test" is a nested dict or not.
If it is nested dict I want to know the "key" of the nested dictionary, How can I solve this.
iterate and check
for key, value in outer_dict.items():
if isinstance(value, dict):
print(key)

Work with nested objects using couchdb-python

Disclaimer: Both Python and CouchDB are new for me. So far my "programming" has mostly consisted of Bash scripts.
I'm trying to create a small script that updates objects in a CouchDB database. The objects however aren't created by my script but by an App called Tap Forms that uses CouchDB for sync. Basically I'm trying to automatically update the content of the app. That also means I can't really influence the structure or names of the objects in CouchDB.
The Database is mostly filled with objects of this structure:
{
"_id": "rec-3b17...",
"_rev": "21-cdf6...",
"values": {
"fld-c3d4...": 4,
"fld-1def...": 1000000000000,
"fld-bb44...": 760000000000,
"fld-a44f...": "admin,name",
"fld-5fc0...": "SSD",
"fld-642c...": true,
},
"deviceName": "MacBook Air",
"dateModified": "2019-02-08T14:47:06.051Z",
"dateCreated": "2019-02-08T11:33:00.018Z",
"type": "frm-7ff3...",
"dbID": "db-1435...",
"form": "frm-7ff3..."
}
I shortened the numbers a bit and removed some entries to increase readability.
Now the actual values I'm trying to update are within the "values" : {...} array (or object, or list, guess I don't have much experience with JSON either).
As I know some of these values, I managed to create view that finds the _id of an object on the server. I then use the python-couchdb module as described in documentation:
for item in db.view('CustomViews/test2', key="GENERIC"):
doc = db[item.id]
This gives me the object. However I want to update one of the values within the values array, lets say fld-c3d4.... But how? Using doc['values'] = 'new_value' updates the whole array. I tried other (seemingly logical) ways along the lines of doc['values['fld-c3d4']'] = 'new_value' but couldn't wrap my head around it. I couldn't find an example in any documentation.
So here's a example how to update the fld-c3d4.
You have your document that represent a dictionary with nested dictionary.
If you want to get the values, you will do something like this:
values = doc['values']
Now the variable values points to the values in your document.
From there, you can access a sub value:
values['fld-c3d4'] = 'new value'
If you want to directly update the value from the doc, you just have to chain those operations:
doc['values']['fld-c3d4'] = 'new value'

Using A Python List or String in Dictionary Lookup?

Use Case
I am making a factory type script in Python that consumes XML and based on that XML, returns information from a specific factory. I have created a file that I call FactoryMap.json that stores the mapping between the location an item can be found in XML and the appropriate factory.
Issue
The JSON in my mapping file looks like:
{
"path": "['project']['builders']['hudson.tasks.Shell']",
"class": "bin.classes.factories.step.ShellStep"
}
path is where the element can be found in the xml once its converted to a dict.
class is the corresponding path to the factory that can consume that elements information.
In order to do anything with this, I need to descend into the dictionaries structure, which would look like this if I didn't have to draw this information from a file(note the key reference = 'path' from my json'):
configDict={my xml config dict}
for k,v in configDict['project']['builders']['hudson.tasks.Shell'].iteritems():
#call the appropriate factory
The issue is that if I look up the path value as a string or a list, I can not use it in 'iteritems'():
path="['project']['builders']['hudson.tasks.Shell']" #this is taken from the JSON
for k,v in configDict[path].iteritems():
#call the appropriate factory
This returns a key error stating that I can't use a string as the key value. How can I used a variable as the key for that python dictionary?
You could use eval:
eval( "configDict"+path )
You can use the eval() function to evaluate your path into an actual dict object vs a string. Something like this is what I'm referring to:
path="['project']['builders']['hudson.tasks.Shell']" #this is taken from the JSON
d = eval("configDict%s" % path)
for k,v in d.iteritems():
#call the appropriate factory

Retrieve JSON key and value

I am POSTing a .json object to my server with different keys attached.
ID, time, content
On my server I want to then wrap this again in another .json file with another APIs key and value formatting.
So... I want to store the key and value for 'content'
Currently i can obtain the value for 'content by:
content = json_obj['content']
But this only returns the value. What is the syntax for storing the key and value in content? The desirable outcome:
content = {'content' : "........."}
Your JSON_obj here is acting as a dictionary, so you can use Python's items (Python 3+) or iteritems (Python 2.7) functions:
for k,v in json_obj.iteritems():
foo = {k: v}
# do something with foo
Solved, thanks SuperSaiyan you triggered this thought.
Just create a new dictionary:
content = json_obj['content']
test_obj = {'content':content}
Could also:
test_obj = {'content':json_obj['content']}

Jinja2 Array Iteration Problems

I am getting some unusual behaviour with Jinja2 and iterating through an array which I can't quite put my finger on. I am passing a dictionary into Jinja2, one of the values of the dictionary is an array. A simple example of this works okay.
mydict = {
'testvar1': 'this is a test var 1',
'testvar2': 'this is a test var 2',
'testvar3': ['test','test','test','test','test'],
}
This is my Jinja template
{{ testvar1 }}
{{ testvar2 }}
{% for var in testvar3 %}
{{ var }}
{% endfor %}
Now this actually works, I get the below output
this is a testvar1
this is a testvar2
test
test
test
test
test
test
However, I am generating a dictionary using the CSV import utility. Now I am aware that this tool imports all values as strings, so I am separating the 'array field' with dashes so I can split them later on.
input_file = csv.DictReader(open("./my_path/import.csv"))
for row in input_file:
for key, value in row.iteritems():
if '-' in value:
value = value.split('-')
When I print both the array value from the dictionary created manually and the dictionary created by the csv import they look identical.
['test','test','test','test','test']
However when I generate the configuration using the dictonary populated by the csv import, the output I get is completely different.
testvar1
testvar2
t
e
s
t
t
e
s
t
And so forth...
Now it seems it is iterating over the values as if is were a simple string value, printing one character at a time for each iteration of the loop.
But it works perfectly when making the dictionary manually.
Any ideas? If there is a cleaner way to do this I'm all ears.
Thanks in advance.
My Problem was I had the wrong JSON syntax in my database.
{
"tags" : "[my, wrong, array]"
}
ended up beeing interpreted as unicode object from python which explains why iterating over it was iterating over every character.
the right syntax is:
{
"tags": [
"tech",
"python",
"flask"
]
}

Categories

Resources