Python how to insert objects in nested lists - python

How do I insert an object in nested lists. I get json response that doesn't return a a certain object for certain a condition
data.json
Note: in 'steps' list, the 3rd index did not return result
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"status": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"status": "passed"
}
},
{
"name": "map should display"
}
]
}
],
"keyword": "Feature",
"name": "login",
"status": "passed"
}
]
What I want to achieve:
I want to insert a 'result' object if it is absent
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"status": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"status": "passed"
}
},
{
"name": "map should display"
"result": {
"status": "skipped"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"status": "passed"
}
]
What i've done so far (pseudo):
with open('data.json') as data_file:
data = json.load(data_file)
#nested for loops??
#if x.has_key('result') == False
#insert result object

The following should word for you:
for step in data[0]['elements'][0]['steps']:
if 'result' not in step:
step['result'] = {"status": "skipped"}
More generic solution:
for d in data:
for element in d['elements']:
for step in element['steps']:
if 'result' not in step:
step['result'] = {"status": "skipped"}

Related

Is there a way to add curly brackets around a list of dictionaries already existing within a JSON file?

I currently have two JSONS that I want to merge into one singular JSON, additionally I want to add in a slight change.
Firstly, these are the two JSONS in question.
An intents JSON:
[
{
"ID": "G1",
"intent": "password_reset",
"examples": [
{
"text": "I forgot my password"
},
{
"text": "I can't log in"
},
{
"text": "I can't access the site"
},
{
"text": "My log in is failing"
},
{
"text": "I need to reset my password"
}
]
},
{
"ID": "G2",
"intent": "account_closure",
"examples": [
{
"text": "I want to close my account"
},
{
"text": "I want to terminate my account"
}
]
},
{
"ID": "G3",
"intent": "account_creation",
"examples": [
{
"text": "I want to open an account"
},
{
"text": "Create account"
}
]
},
{
"ID": "G4",
"intent": "complaint",
"examples": [
{
"text": "A member of staff was being rude"
},
{
"text": "I have a complaint"
}
]
}
]
and an entities JSON:
[
{
"ID": "K1",
"entity": "account_type",
"values": [
{
"type": "synonyms",
"value": "business",
"synonyms": [
"corporate"
]
},
{
"type": "synonyms",
"value": "personal",
"synonyms": [
"vanguard",
"student"
]
}
]
},
{
"ID": "K2",
"entity": "beverage",
"values": [
{
"type": "synonyms",
"value": "hot",
"synonyms": [
"heated",
"warm"
]
},
{
"type": "synonyms",
"value": "cold",
"synonyms": [
"ice",
"freezing"
]
}
]
}
]
The expected outcome is to create a JSON file that mimics this structure:
{
"intents": [
{
"intent": "password_reset",
"examples": [
{
"text": "I forgot my password"
},
{
"text": "I want to reset my password"
}
],
"description": "Reset a user password"
}
],
"entities": [
{
"entity": "account_type",
"values": [
{
"type": "synonyms",
"value": "business",
"synonyms": [
"company",
"corporate",
"enterprise"
]
},
{
"type": "synonyms",
"value": "personal",
"synonyms": []
}
],
"fuzzy_match": true
}
],
"metadata": {
"api_version": {
"major_version": "v2",
"minor_version": "2018-11-08"
}
},
"dialog_nodes": [
{
"type": "standard",
"title": "anything_else",
"output": {
"generic": [
{
"values": [
{
"text": "I didn't understand. You can try rephrasing."
},
{
"text": "Can you reword your statement? I'm not understanding."
},
{
"text": "I didn't get your meaning."
}
],
"response_type": "text",
"selection_policy": "sequential"
}
]
},
"conditions": "anything_else",
"dialog_node": "Anything else",
"previous_sibling": "node_4_1655399659061",
"disambiguation_opt_out": true
},
{
"type": "event_handler",
"output": {
"generic": [
{
"title": "What type of account do you hold with us?",
"options": [
{
"label": "Personal",
"value": {
"input": {
"text": "personal"
}
}
},
{
"label": "Business",
"value": {
"input": {
"text": "business"
}
}
}
],
"response_type": "option"
}
]
},
"parent": "slot_9_1655398217028",
"event_name": "focus",
"dialog_node": "handler_6_1655398217052",
"previous_sibling": "handler_7_1655398217052"
},
{
"type": "event_handler",
"output": {},
"parent": "slot_9_1655398217028",
"context": {
"account_type": "#account_type"
},
"conditions": "#account_type",
"event_name": "input",
"dialog_node": "handler_7_1655398217052"
},
{
"type": "standard",
"title": "business_account",
"output": {
"generic": [
{
"values": [
{
"text": "We have notified your corporate security team, they will be in touch to reset your password."
}
],
"response_type": "text",
"selection_policy": "sequential"
}
]
},
"parent": "node_3_1655397279884",
"next_step": {
"behavior": "jump_to",
"selector": "body",
"dialog_node": "node_4_1655399659061"
},
"conditions": "#account_type:business",
"dialog_node": "node_1_1655399028379",
"previous_sibling": "node_3_1655399027429"
},
{
"type": "standard",
"title": "intent_collection",
"output": {
"generic": [
{
"values": [
{
"text": "Thank you for confirming that you want to reset your password."
}
],
"response_type": "text",
"selection_policy": "sequential"
}
]
},
"next_step": {
"behavior": "jump_to",
"selector": "body",
"dialog_node": "node_3_1655397279884"
},
"conditions": "#password_reset",
"dialog_node": "node_3_1655396920143",
"previous_sibling": "Welcome"
},
{
"type": "frame",
"title": "account_type_confirmation",
"output": {
"generic": [
{
"values": [
{
"text": "Thank you"
}
],
"response_type": "text",
"selection_policy": "sequential"
}
]
},
"parent": "node_3_1655396920143",
"context": {},
"next_step": {
"behavior": "skip_user_input"
},
"conditions": "#password_reset",
"dialog_node": "node_3_1655397279884"
},
{
"type": "standard",
"title": "personal_account",
"output": {
"generic": [
{
"values": [
{
"text": "We have sent you an email with a password reset link."
}
],
"response_type": "text",
"selection_policy": "sequential"
}
]
},
"parent": "node_3_1655397279884",
"next_step": {
"behavior": "jump_to",
"selector": "body",
"dialog_node": "node_4_1655399659061"
},
"conditions": "#account_type:personal",
"dialog_node": "node_3_1655399027429"
},
{
"type": "standard",
"title": "reset_confirmation",
"output": {
"generic": [
{
"values": [
{
"text": "Do you need assistance with anything else today?"
}
],
"response_type": "text",
"selection_policy": "sequential"
}
]
},
"digress_in": "does_not_return",
"dialog_node": "node_4_1655399659061",
"previous_sibling": "node_3_1655396920143"
},
{
"type": "slot",
"output": {},
"parent": "node_3_1655397279884",
"variable": "$account_type",
"dialog_node": "slot_9_1655398217028",
"previous_sibling": "node_1_1655399028379"
},
{
"type": "standard",
"title": "welcome",
"output": {
"generic": [
{
"values": [
{
"text": "Hello. How can I help you?"
}
],
"response_type": "text",
"selection_policy": "sequential"
}
]
},
"conditions": "welcome",
"dialog_node": "Welcome"
}
],
"counterexamples": [],
"system_settings": {
"off_topic": {
"enabled": true
},
"disambiguation": {
"prompt": "Did you mean:",
"enabled": true,
"randomize": true,
"max_suggestions": 5,
"suggestion_text_policy": "title",
"none_of_the_above_prompt": "None of the above"
},
"human_agent_assist": {
"prompt": "Did you mean:"
},
"intent_classification": {
"training_backend_version": "v2"
},
"spelling_auto_correct": true
},
"learning_opt_out": false,
"name": "Reset Password",
"language": "en",
"description": "Basic Password Reset Request"
}
So what I am missing in my original files, is essentially:
"intents":
and for the entities file:
"entities"
at the start of each list of dictionaries.
Additionally, I would need to wrap the whole thing in curly braces to comply with json formatting.
As seen, the final goal is not just appending these two to one another but the file technically continues with some other JSON code that I have yet to write and deal with.
My question now is as follows; by what method can I either add in these words and the braces to the individual files, then combine them into a singular JSON or alternatively by what method can I read in these files and combine them with the changes all in one go?
The new output file closing on a curly brace after the entities list of dicts is an acceptable outcome for me at the time, so that I can continue to make changes and hopefully further learn from this how to do these changes in future when I get there.
TIA
JSON is only a string format, you can it load in a language structure, in python that is list and dict, do what you need then dump it back, so you don't "add strings" and "add brackets", on modify the structure
file = 'intents.txt'
intents = json.load(open(file)) # load a list
file = 'entities.txt'
entities = json.load(open(file)) # load a list
# create a dict
content = {
"intents": intents,
"entities": entities
}
json.dump(content, open(file, "w"))
If you're reading all the json in as a string, you can just prepend "{'intents':" to the start and append a closing "}".
myJson = "your json string"
myWrappedJson = '{"intents":' + myJson + "}"

Microsoft Teams bot Adaptive Cards Action is received in on_message_activity without data

My bot returns an adaptive card in 1:1 private chat with user, the adaptive card configuration is like this,
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": f"{jiradetail.summary}",
}
]
}
],
"actions": [
{
"type": "Action.ShowCard",
"title": "Comment",
"card": {
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Input.Text",
"id": "comment",
"isMultiline": True,
"placeholder": "Enter your comment"
}
],
"actions": [
{
"type": "Action.Submit",
"title": "OK",
"data": "**jiraid**"
}
]
}
}
]
}
As you could see, there is a 'comment' textbox and a 'Ok' Action (type Action.Submit, and hidden data->jiraid), the card will be as shown below,
Now on click on this Ok button, I am receiving the activity in ,
on_message_activity, with the user entered value in the commentbox in the field,
turn_context.activity.value
but i couldnt get the hidden data which i mapped to the action button, the below picture shows the inspected value of 'turn_context.activity'.
How can i get the mapped data to this action?
Note: I was also expecting the callback to be, on_teams_messaging_extension_submit_action , but this callback is never called, instead only on_message_activity is called. I assume, its because its an 1:1 conversation and its not invoked via the messageextensions. Any experts please confirm.
Regarding "on_teams_messaging_extension_submit_action" - it's not because it's a 1-1, rather it's because it is NOT a "message extension", it's just a regular Adaptive Card action.
With regards the main issue, about the data not appearing, try to avoid having a direct string value as the "data" payload, and instead try with an object, like this:
...
"data": {"value": "**jiraid**"}
...
Got the answer here,
https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-actions#
For easy reference, this what we are supposed to do,
Adaptive Cards support three action types:
Action.OpenUrl
Action.Submit
Action.ShowCard
In addition to the
actions mentioned above, you can modify the Adaptive Card
Action.Submit payload to support existing Bot Framework actions using
a msteams property in the data object of Action.Submit. The below
sections detail how to use existing Bot Framework actions with
Adaptive Cards.
So the updated payload will be, refer the payload 'msteams' under action->data,
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": f"{jiradetail.summary}",
}
]
}
],
"actions": [
{
"type": "Action.ShowCard",
"title": "Comment",
"card": {
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Input.Text",
"id": "comment",
"isMultiline": True,
"placeholder": "Enter your comment"
}
],
"actions": [
{
"type": "Action.Submit",
"title": "OK",
"data": {
"msteams": {
"type": "invoke",
"value": {"jiraid":f"{jiradetail.issueid}"}
}
}
]
}
}
]
}

Python, How to zip and restructure complex data set

I am a new python user, and I have just been getting familiar with restructuring data with the zip function, however I am now faced with a challenging data set that i have to restructure. I have 3 json responses that I have to merge from my end, the data sets are identical in design and would have the same length, they just differ from environments they ran on.
Let 3 files be the same values for brevity: qa.json | dev.json | prod.json
Note: This outer object is array/list of object, I just put one object for brevity
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"status": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"status": "passed"
}
},
{
"name": "map should display",
"result": {
"status": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"status": "passed"
}
]
What I want to achieve:
Note: i want to merge them in one set with different environments reflecting the status
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"qa": "passed",
"prod": "passed",
"dev": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"qa": "passed",
"prod": "passed",
"dev": "passed"
}
},
{
"name": "map should display",
"result": {
"qa": "passed",
"prod": "passed",
"dev": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"qa": "passed",
"prod": "passed",
"dev": "passed"
}
]
What i have done so far:
I come from a javascript background so i im still getting familiar with python logic
import json
with open('qa.json') as data_file:
qa = json.load(data_file)
with open('dev.json') as data_file:
dev = json.load(data_file)
with open('prod.json') as data_file:
prod = json.load(data_file)
json_list = [{SOME STRUCT} for q, d, p in zip(qa, dev, prod)]
I don't have a lot of time so I'm posting what I believe is a working solution to your problem even if it's slightly messy. If I have time I'll edit it.
Code
import json
data = """
[
{
"elements": [{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [{
"name": "a valid user name and password",
"result": {
"status": "passed"
}
}, {
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"status": "passed"
}
}, {
"name": "map should display",
"result": {
"status": "passed"
}
}]
}],
"keyword": "Feature",
"name": "login",
"status": "passed"
},
{
"elements": [{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [{
"name": "a valid user name and password",
"result": {
"status": "passed"
}
}, {
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"status": "failed"
}
}, {
"name": "map should display",
"result": {
"status": "passed"
}
}]
}],
"keyword": "Feature",
"name": "login",
"status": "passed"
}
]
"""
def get_result(envData, objIndex, elementIndex, stepIndex):
return envData[objIndex]['elements'][elementIndex]['steps'][stepIndex]['result']['status']
def set_combined_results(combinedData, objIndex, elementIndex, stepIndex, results):
resultNode = combinedData[objIndex]['elements'][elementIndex]['steps'][stepIndex]['result']
resultNode.update({ 'qa': results[0], 'prod': results[1], 'dev': results[2] })
if __name__ == '__main__':
qAData = json.loads(data)
prodData = json.loads(data)
devData = json.loads(data)
combinedData = json.loads(data)
for objIndex, obj in enumerate(combinedData):
for elementIndex, element in enumerate(obj['elements']):
for stepIndex, _ in enumerate(element['steps']):
qAResult = get_result(qAData, objIndex, elementIndex, stepIndex)
prodResult = get_result(prodData, objIndex, elementIndex, stepIndex)
devResult = get_result(devData, objIndex, elementIndex, stepIndex)
combinedResults = (qAResult, prodResult, devResult)
set_combined_results(combinedData, objIndex, elementIndex, stepIndex, combinedResults)
qAAggregateResult = qAData[objIndex]['status']
prodAggregateResult = prodData[objIndex]['status']
devAggregateResult = devData[objIndex]['status']
del combinedData[objIndex]['status']
combinedData[objIndex]['qa'] = qAAggregateResult
combinedData[objIndex]['prod'] = prodAggregateResult
combinedData[objIndex]['dev'] = devAggregateResult
print(json.dumps(combinedData, indent=True))
Output
[
{
"keyword": "Feature",
"name": "login",
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "a valid user name and password"
},
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "a valid user clicking on the login button after typing in user name and password"
},
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "map should display"
}
]
}
],
"dev": "passed",
"prod": "passed",
"qa": "passed"
},
{
"keyword": "Feature",
"name": "login",
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "a valid user name and password"
},
{
"result": {
"qa": "failed",
"status": "failed",
"dev": "failed",
"prod": "failed"
},
"name": "a valid user clicking on the login button after typing in user name and password"
},
{
"result": {
"qa": "passed",
"status": "passed",
"dev": "passed",
"prod": "passed"
},
"name": "map should display"
}
]
}
],
"dev": "failed",
"prod": "failed",
"qa": "failed"
}
]
This is a recursive merge implementation. It will merge arbitrary types of Python objects, such that anything but dicts must be equal when merged.
For dicts, it will allow merging if the same keys are associated with mergable values in those where the key is present. Any dict keys equalling the parameter fieldname will be suffixed with an index before merging:
from copy import deepcopy
from itertools import chain
def merge(field_name, *objs):
# Make sure all objs are of same type
types = list(set(map(type, objs)))
if not len(set(map(type, objs))) == 1:
raise Exception('Cannot merge objects of different types: {types}'.format(types=types))
first = objs[0]
# for any random objects, make sure they are equal!
if not isinstance(first, (list, tuple, dict)):
if not len(set(objs)) == 1:
raise Exception("Cannot merge non-equal objects that aren't dicts: {objs}".format(objs=objs))
return deepcopy(first)
# for lists, tuples: zip 'em and merge the zipped elements
if isinstance(first, (list, tuple)):
return [merge(field_name, *zipped) for zipped in zip(*objs)]
# dicts
result_dict = {}
keys = list(set(chain.from_iterable(d.keys() for d in objs)))
try:
keys.remove(field_name)
except ValueError:
pass
for k in keys:
# merge values from all dicts where key is present
result_dict[k] = merge(field_name, *(d[k] for d in objs if k in d))
for i, d in enumerate(objs):
if field_name in d:
result_dict['{f}_{i}'.format(f=field_name, i=i)] = d[field_name]
return result_dict
This can now be used on dev, qa, prod that are dicts of the structure given by th OP:
>>> from pprint import pprint
>>> pprint(merge('status', qa, dev, prod))
[{'elements': [{'keyword': 'Scenario',
'name': 'valid user can login site',
'steps': [{'name': 'a valid user name and password',
'result': {'status_0': 'passed',
'status_1': 'passed',
'status_2': 'passed'}},
{'name': 'a valid user clicking on the login button after typing in user name and password',
'result': {'status_0': 'passed',
'status_1': 'passed',
'status_2': 'passed'}},
{'name': 'map should display',
'result': {'status_0': 'passed',
'status_1': 'passed',
'status_2': 'passed'}}]}],
'keyword': 'Feature',
'name': 'login',
'status_0': 'passed',
'status_1': 'passed',
'status_2': 'passed'}]
This is, of course, not fully generic, e.g. it only "deep" merges sequences when they are lists or tuples, but it should be decent enough for data structures loaded from json. I hope it helps you find a solution.
Because each object in the list is a dict you can use dict.update mehthod to update a dict.
f.e.
a = [{'one': 1}, {'three': 3}]
b = [{'one': 1}, {'two': 2}] # {'one': 1} is duplicate with same value
c = [{'a': 'aaa'}, {'two': 22}] # {'two': 22} is duplicate with different value
for x, y, z in zip(a, b, c):
x.update(y)
x.update(z)
Now x would be [{'a': 'aaa', 'one': 1}, {'three': 3, 'two': 22}]
For those json files you mentioned, it would be;
import json
from pprint import pprint
qa = '''
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"qa": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"qa": "passed"
}
},
{
"name": "map should display",
"result": {
"qa": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"qa": "passed"
}
]
'''
dev = '''
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"dev": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"dev": "passed"
}
},
{
"name": "map should display",
"result": {
"dev": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"dev": "passed"
}
]
'''
prod = '''
[
{
"elements": [
{
"keyword": "Scenario",
"name": "valid user can login site",
"steps": [
{
"name": "a valid user name and password",
"result": {
"prod": "passed"
}
},
{
"name": "a valid user clicking on the login button after typing in user name and password",
"result": {
"prod": "passed"
}
},
{
"name": "map should display",
"result": {
"prod": "passed"
}
}
]
}
],
"keyword": "Feature",
"name": "login",
"prod": "passed"
}
]
'''
qa = json.loads(qa)
dev = json.loads(dev)
prod = json.loads(prod)
for q, p, d in zip(qa, dev, prod):
# update all keys but 'elements'
q.update({k: v for k, v in p.items() if k != 'elements'})
q.update({k: v for k, v in d.items() if k != 'elements'})
# update the three 'result' dict
for i in range(3):
q['elements'][0]['steps'][i]['result'].update(p['elements'][0]['steps'][i]['result'])
q['elements'][0]['steps'][i]['result'].update(d['elements'][0]['steps'][i]['result'])
pprint(qa)
Output;
[{'dev': 'passed',
'elements': [{'keyword': 'Scenario',
'name': 'valid user can login site',
'steps': [{'name': 'a valid user name and password',
'result': {'dev': 'passed',
'prod': 'passed',
'qa': 'passed'}},
{'name': 'a valid user clicking on the login button '
'after typing in user name and password',
'result': {'dev': 'passed',
'prod': 'passed',
'qa': 'passed'}},
{'name': 'map should display',
'result': {'dev': 'passed',
'prod': 'passed',
'qa': 'passed'}}]}],
'keyword': 'Feature',
'name': 'login',
'prod': 'passed',
'qa': 'passed'}]

Unable to pull data from json using python

I have the following json
{
"response": {
"message": null,
"exception": null,
"context": [
{
"headers": null,
"name": "aname",
"children": [
{
"type": "cluster-connectivity",
"name": "cluster-connectivity"
},
{
"type": "consistency-groups",
"name": "consistency-groups"
},
{
"type": "devices",
"name": "devices"
},
{
"type": "exports",
"name": "exports"
},
{
"type": "storage-elements",
"name": "storage-elements"
},
{
"type": "system-volumes",
"name": "system-volumes"
},
{
"type": "uninterruptible-power-supplies",
"name": "uninterruptible-power-supplies"
},
{
"type": "virtual-volumes",
"name": "virtual-volumes"
}
],
"parent": "/clusters",
"attributes": [
{
"value": "true",
"name": "allow-auto-join"
},
{
"value": "0",
"name": "auto-expel-count"
},
{
"value": "0",
"name": "auto-expel-period"
},
{
"value": "0",
"name": "auto-join-delay"
},
{
"value": "1",
"name": "cluster-id"
},
{
"value": "true",
"name": "connected"
},
{
"value": "synchronous",
"name": "default-cache-mode"
},
{
"value": "true",
"name": "default-caw-template"
},
{
"value": "blah",
"name": "default-director"
},
{
"value": [
"blah",
"blah"
],
"name": "director-names"
},
{
"value": [
],
"name": "health-indications"
},
{
"value": "ok",
"name": "health-state"
},
{
"value": "1",
"name": "island-id"
},
{
"value": "blah",
"name": "name"
},
{
"value": "ok",
"name": "operational-status"
},
{
"value": [
],
"name": "transition-indications"
},
{
"value": [
],
"name": "transition-progress"
}
],
"type": "cluster"
}
],
"custom-data": null
}
}
which im trying to parse using the json module in python. I am only intrested in getting the following information out of it.
Name Value
operational-status Value
health-state Value
Here is what i have tried.
in the below script data is the json returned from a webpage
json = json.loads(data)
healthstate= json['response']['context']['operational-status']
operationalstatus = json['response']['context']['health-status']
Unfortunately i think i must be missing something as the above results in an error that indexes must be integers not string.
if I try
healthstate= json['response'][0]
it errors saying index 0 is out of range.
Any help would be gratefully received.
json['response']['context'] is a list, so that object requires you to use integer indices.
Each item in that list is itself a dictionary again. In this case there is only one such item.
To get all "name": "health-state" dictionaries out of that structure you'd need to do a little more processing:
[attr['value'] for attr in json['response']['context'][0]['attributes'] if attr['name'] == 'health-state']
would give you a list of of matching values for health-state in the first context.
Demo:
>>> [attr['value'] for attr in json['response']['context'][0]['attributes'] if attr['name'] == 'health-state']
[u'ok']
You have to follow the data structure. It's best to interactively manipulate the data and check what every item is. If it's a list you'll have to index it positionally or iterate through it and check the values. If it's a dict you'll have to index it by it's keys. For example here is a function that get's the context and then iterates through it's attributes checking for a particular name.
def get_attribute(data, attribute):
for attrib in data['response']['context'][0]['attributes']:
if attrib['name'] == attribute:
return attrib['value']
return 'Not Found'
>>> data = json.loads(s)
>>> get_attribute(data, 'operational-status')
u'ok'
>>> get_attribute(data, 'health-state')
u'ok'
json['reponse']['context'] is a list, not a dict. The structure is not exactly what you think it is.
For example, the only "operational status" I see in there can be read with the following:
json['response']['context'][0]['attributes'][0]['operational-status']

How to parse JSON in a Django View

I post some JSON to a view. I want to now parse the data and add it to my database.
I need to get the properties name and theme and iterate over the array pages. My JSON is as follows:
{
"name": "xaAX",
"logo": "",
"theme": "b",
"fullSiteLink": "http://www.hello.com",
"pages": [
{
"id": "1364484811734",
"name": "Page Name",
"type": "basic",
"components": {
"img": "",
"text": ""
}
},
{
"name": "Twitter",
"type": "twitter",
"components": {
"twitter": {
"twitter-username": "zzzz"
}
}
}
]
}
Here is what I have so far:
def smartpage_create_ajax(request):
if request.POST:
# get stuff and loop over each page?
return HttpResponse('done')
python provides json to encode/decode json
import json
json_dict = json.loads(request.POST['your_json_data'])
json_dict['pages']
[
{
"id": "1364484811734",
"name": "Page Name",
"type": "basic",
"components": {
"img": "",
"text": ""
}
},
{
"name": "Twitter",
"type": "twitter",
"components": {
"twitter": {
"twitter-username": "zzzz"
}
}
},
}
]

Categories