what is the JSON path expression to fetch "item1" , "item2" without knowing in advance the names of these keys.
{
"item_group" : "This is item group",
"items": {
"item1": {
"name1": "value1",
"name2": {
"value2": "value2"
},
"name3": {
"param1": "This is param1"
}
},
"item2": {
"name11": "value11",
"name22": {
"value22": "value22"
},
"name33": {
"param2": "This is param2"
}
}
}
}
You probably want dict["items"].items(). It will return a list of key/value tuples. For an example iterating over the keys:
for key, _ in dict["items"].items():
pass
for..in loop worked!
for(var prop in obj) {
console.log("Key_Name: " + prop);
}
Related
I have the following json output assigned to a variable called "mydict":
{
"data": {
"endpoints": {
"edges": [
{
"node": {
"name": "test1.net",
"ipAddress": "1.2.3.4"
}
},
{
"node": {
"name": "test2.net",
"ipAddress": "4.3.2.1"
}
},
{
"node": {
"name": "test3.net",
"ipAddress": "0.0.0.0"
}
}
]
}
}
}
I'm able to print out a single "name" value with:
print("Dictionary contains: ",mydict['data']['endpoints']['edges'][1]['node']['name'])
But with how the data is nested, I'm not sure how to iterate through each "name" to get a print of only those values. Any recommendations? Thank you!
for edge in mydict['data']['endpoints']['edges']:
print(edge['node']['name'])
I've a requirement where I've to update/merge nested child of a dict. I've tried dict.update but it strips the sibling (get_users in the the example below).
I can update a dict like tree['endpoints']['get_tickets']['handlers']['after'] = 'new_after_handler', but those dict keys will be dynamic, coming from string, any idea how to achieve this?
So I basically want to get the test below passed, of course endpoints.get_tickets.handlers will be dynamic.
def test_partial_merge(self):
source = {
"name": "tucktock",
"endpoints": {
"get_tickets": {
"path": "tickets",
"handlers": {
"after": "after_handler",
"after_each": "after_each_handler"
}
},
"get_users": {},
},
}
merging = {
"after": "new_after_handler",
}
expected = {
"name": "tucktock",
"endpoints": {
"get_tickets": {
"path": "tickets",
"handlers": {
"after": "new_after_handler",
"after_each": "after_each_handler"
}
},
"get_users": {},
},
}
merger = Merger()
result = merger.merge(source, merging, "endpoints.get_tickets.handlers")
self.assertEqual(expected, result)
You can do something like this:
source = {
"name": "tucktock",
"endpoints": {
"get_tickets": {
"path": "tickets",
"handlers": {
"after": "after_handler",
"after_each": "after_each_handler"
}
},
"get_users": {},
},
}
merging = {
"after": "new_after_handler",
}
expected = {
"name": "tucktock",
"endpoints": {
"get_tickets": {
"path": "tickets",
"handlers": {
"after": "new_after_handler",
"after_each": "after_each_handler"
}
},
"get_users": {},
},
}
def merge(a, b, dict_path): # modifies a in place
for key in dict_path:
a = a[key]
a.update(b)
merge(source, merging, "endpoints.get_tickets.handlers".split('.'))
print(source == expected)
>>> True
In your Merger.merge method you can convert the source to collections.defaultdict(dict). Then you can iterate over the third parameter ("endpoints.get_tickets.handlers".split('.')) and iteratively go to the level of depth you need, then update this part.
Example:
def merge(source, merging, path):
result = defaultdict(dict)
result.update(source)
current_part = result
for key in path.split('.'):
current_level = current_level[key]
current_level.update(merging)
return result
I have a simple json in python that looks like :
{
"list": [{
"key1": "value1"
},
{
"key1": "value1"
}
]
}
I want to transform this to the following json. Any suggestions how I can do it with python without installing additional libraries?
{
"list": [{
"keys": {
"name": "key1",
"value": "value1"
}
}, {
"keys": {
"name": "key1",
"value": "value1"
}
}]
}
Not sure from your question if you already have the json read into a variable, or if it is in a file. This is assuming you have it in a variable already:
in_json = {
"list": [{
"key1": "value1"
},
{
"key2": "value2"
}
]
}
out_json = {"list":[]}
for kd in in_json["list"]:
sub_kd = {"keys": {}}
for k,v in kd.iteritems():
sub_kd["keys"]["name"] = k
sub_kd["keys"]["value"] = v
out_json["list"].append(sub_kd)
print(out_json)
It just loops through the json making dictionaries to append to the out_json dictionary. You could make this print pretty with the json library and also save to file with it
You didn't indicate exactly what contains the JSON data is in, so I've put it all in a string in the example code below and uses the json.loads() function to turn it into a Python dictionary. If it's in a file, you can use the module's json.load() function instead.
It also make the assume that each sub-JSON object in the "list" list consists of only one key/value pair as shown in your question.
The code below changes the deserialized dictionary in-place and pretty-prints the result of doing that by using the json.dumps() function to reserialize it.
Note that I changed the keys and values in sample input JSON slightly to make it easier to see the correspondence between it and the printed results.
import json
json_in = '''
{
"list": [
{
"key1": "value1"
},
{
"key2": "value2"
}
]
}
'''
json_data = json.loads(json_in) # Deserialize.
for i, obj in enumerate(json_data['list']):
# Assumes each object in list contains only one key, value pair.
newobj = { 'name': next(iter(obj.keys())),
'value': next(iter(obj.values()))}
json_data['list'][i] = {'keys': newobj}
print(json.dumps(json_data, indent=4)) # Reserialize and print.
Printed result:
{
"list": [
{
"keys": {
"name": "key1",
"value": "value1"
}
},
{
"keys": {
"name": "key2",
"value": "value2"
}
}
]
}
I have a json which looks like below
result_json = {
"status":"Gov info",
"user_input":[
{
"rule":"Location"
},
{
"des": "This is for location1",
"value": 1
},
{
"des": "This is for location2",
"value": 2
},
{
"rule":"District"
},
{
"des": "This is for district1",
"value": 1
},
{
"des": "This is for district2",
"value": 2
},
{
"des": "This is for district3",
"value": 3
},
{
"des": "This is for district4",
"value": 4
},
{
"rule":"Country"
},
{
"des": "This is for country1",
"value": 1
},
{
"rule":"Continent"
},
{
"des": "This is for continent1",
"value": 1
},
{
"des": "This is for continent2",
"value": 2
},
],
"source":"Gov",
"id":"5ass1"
}
I also have a list like so
lookup = [u'Location', u'District', u'Country', u'Continent']
Now what I want to do is that I look at each value of the list, check against the json for the same value (the value is stored against rule key) and get the sub json right after it until I hit the next rule. For example
The first value in the list lookup is Location. Now I loop through user_input key's value, check against the sub key rule and find out that the value Location matches and right after that store the subsequent dictionaries until I hit the next key rule. So for lookup value Location, after checking against the json and collecting the subsequent dictionary, this is how I will store
filtered_output = {
"Location":[
{
"des":"This is for location1",
"value":1
},
{
"des":"This is for location2",
"value":2
}
]
}
Now I look for next lookup value which is District and the subsequent part of json that will be stored is
filtered_output = {
"Location":[
{
"des":"This is for location1",
"value":1
},
{
"des":"This is for location2",
"value":2
}
],
"District":[
{
"des":"This is for district1",
"value":1
},
{
"des":"This is for district2",
"value":2
},
{
"des":"This is for district3",
"value":3
},
{
"des":"This is for district4",
"value":4
}
]
}
I tried doing something like below
filtered_output = {}
for i in lookout:
temp_json = []
for j in result_json["user_input"]:
if j.get("rule") == i:
temp_json.append(j)
Here it only stores the dictionary that contains the key rule but doesn't continue further until it hits the next rule key. I am not sure how to make this work. Any help will be appreciated.
I would first transform your input to the format you want and them I would onluy filter the keys, something like this:
user_input = result_json["user_input"]
transformed_user_input = {}
for el in user_input:
if "rule" in el:
current_rule = el["rule"]
transformed_user_input[current_rule] = []
else:
transformed_user_input[current_rule].append(el)
lookup = [u'Location', u'District', u'Country', u'Continent']
filtered_user_input = { key: transformed_user_input[key] for key in lookup}
This way, you process your input only once (don't know how big it is).
I have the following JSON data:
{
"data": {
"databis": {
"dataexit": {
"databis2": {
"1250": { }
}
},
"datanode": {
"20544": { }
}
}
}
}
I want to use it to generate a D3 sunburst diagram, but that requires a different data format:
{
"name": "data",
"children": [
{
"name": "databis",
"children": [
{
"name": "dataexit",
"children": [
{
"name": "databis2",
"size": "1250"
}
]
},
{
"name": "datanode",
"size": "20544"
}
]
}
]
}
How can I do this with Python? I think I need to use a recursive function, but I don't know where to start.
You could use recursive solution with function that takes name and dictionary as parameter. For every item in given dict it calls itself again to generate list of children which look like this: {'name': 'name here', 'children': []}.
Then it will check for special case where there's only one child which has key children with value of empty list. In that case dict which has given parameter as a name and child name as size is returned. In all other cases function returns dict with name and children.
import json
data = {
"data": {
"databis": {
"dataexit": {
"databis2": {
"1250": { }
}
},
"datanode": {
"20544": { }
}
}
}
}
def helper(name, d):
# Collect all children
children = [helper(*x) for x in d.items()]
# Return dict containing size in case only child looks like this:
# {'name': '1250', 'children': []}
# Note that get is used to so that cases where child already has size
# instead of children work correctly
if len(children) == 1 and children[0].get('children') == []:
return {'name': name, 'size': children[0]['name']}
# Normal case where returned dict has children
return {'name': name, 'children': [helper(*x) for x in d.items()]}
def transform(d):
return helper(*next(iter(d.items())))
print(json.dumps(transform(data), indent=4))
Output:
{
"name": "data",
"children": [
{
"name": "databis",
"children": [
{
"name": "dataexit",
"children": [
{
"name": "databis2",
"size": "1250"
}
]
},
{
"name": "datanode",
"size": "20544"
}
]
}
]
}