Accessing json array in python without referring to its name - python

I am new to python and I would like to understand how to access an array in a json object without referring to its name.
The given json object has the below structure
import json
input_json = {
"records": [
{
"values": {
"col1": "1"
},
"no": 1,
},
{
"values": {
"col1": "2"
},
"no": 2,
}
],
"number_of_records": 2
}
myVar = json.load(input_json)
for i in myVar['records']: # How do I replace this line?
print i['values']['col1']
I need to loop through the objects inside the 'records' array. How can I fetch the array without using myVar['records']?
Note that the code cannot depend on the order of the json attributes too. The only thing guaranteed is that the json string would have only one array in it.

input_json = {
"records": [
{
"values": {
"col1": "1"
},
"no": 1,
},
{
"values": {
"col1": "2"
},
"no": 2,
}
],
"number_of_records": 2
}
for anything in input_json:
if isinstance(input_json[anything], list):
for values in input_json[anything]:
print(values['values']['col1'])
You can also further nest the for loop if you don't know the 'values' and 'col1' names.

Related

assigning a json dictionary key value to a variable

I have a json with the following structure.
{
"source": {
"excelsheetname": {
"convert_to_csv": "True",
"tgt_folder": "archieve/datetime=",
"brand": "chicken",
"sheets": {
"sheet1":{
"headers": 5,
"columns": 1
},
"sheet2": {
"headers": 3,
"columns": 2
},
"sheet3": {
"headers": 5,
"columns": 3
},
"sheet4": {
"headers": 3,
"columns": 2
}
}
}
What I am trying to do is create a for loop assign the sheet headers and columns to a variable.
This is what my code looks like:
for i in config['source']['excelsheetname']['sheets'][i]:
if i == "headers":
value = i['headers']
But this code doesnt work, as I keep getting the "TypeError: string indices must be integers"
First, you want to parse the JSON into a Python dictionary:
import json
config_str = """
{
"source": {
"excelsheetname": {
"convert_to_csv": "True",
"tgt_folder": "archieve/datetime=",
"brand": "chicken",
"sheets": {
"sheet1":{
"headers": 5,
"columns": 1
},
"sheet2": {
"headers": 3,
"columns": 2
},
"sheet3": {
"headers": 5,
"columns": 3
},
"sheet4": {
"headers": 3,
"columns": 2
}
}
}
}
}
"""
config = json.loads(config_str)
From your question, I understood that you want to get a list of the headers and a list of the columns. When you iterate over a dictionary in Python, you have two values: the key and the value. We can use the values() method to iterate only over the values. Your code iterates over an expression that includes the loop variable, which doesn't make sense, as the variable doesn't exist until then. You could use a simple for loop to get what you want:
for sheetname, sheet in config["source"]["excelsheetname"]["sheets"].items():
headers = sheet["headers"]
columns = sheet["columns"]
# Processing
print(headers + columns, sheetname) # Just an example of processing
Not quiet sure if i get your question right but this will deliever the integer at key "headers" and "columns" for every sheet in sheets
for i in config['source']['excelsheetname']['sheets'].keys():
if "header" in config['source']['excelsheetname']['sheets'][i].keys():
header_value= config['source']['excelsheetname']['sheets'][i]["headers"]
print(header_value) # store it or do whatever you want
if "columns" in config['source']['excelsheetname']['sheets']
column_value = config['source']['excelsheetname']['sheets'][i]["columns"]
print(column_value ) # store it or do whatever you want

delete json objects, if valued matching

I want to delete json objects if value found in the json body. Please see below code and json body. I tried in python but getting error : [TypeError: list indices must be integers or slices, not str]
import json
import sys
key = ['1']
myData = [
{
"id": 1,
"modifiedBy": "admin",
"fields": {
"Application": "1",
"Endtermin": 23011990
}
},
{
"id": 2,
"modifiedBy": "admin",
"fields": {
"Application": "2",
"Endtermin": 11021990
}
}
]
# delete json objects.
[x for x in myData['fields'] if x["Application"] != 'key']
For example : In the json body, I will look for the Application value, when matching with key, then I want to delete json objects. Here i want to delete first json objects because key value is matching with Application value.
My results looks like here.
myData = [
{
"id": 2,
"modifiedBy": "admin",
"fields": {
"Application": "2",
"Endtermin": 11021990
}
}
]
You mixed several things up here.
myData is a list, therefore you cannot access any item in it via a string (that's what the error tells you)
You should not check for 'key', but for key[0]
key does not need to be a list
So here's how to fix this:
import json
import sys
key = "1" # point 3 from above
myData = [
{
"id": 1,
"modifiedBy": "admin",
"fields": {
"Application": "1",
"Endtermin": 23011990
}
},
{
"id": 2,
"modifiedBy": "admin",
"fields": {
"Application": "2",
"Endtermin": 11021990
}
}
]
# delete json objects. This overwrites myData
myData = [x for x in myData if x["fields"]["Application"] != key] # points 1 and 2
If you really need key to be a list because it may contain several keys, I'd suggest following changes:
keys = ["1", "5"]
# myData is still the same
# ...
myData = [x for x in myData if x["fields"]["Application"] not in keys]
This should yield your desired filtering
[x for x in myData if x['fields']['Application'] not in key]
iterates over the list of entries in myData and check for each entry x whether it's property x['fields']['Application'] is not in the list of key which you want to filter
Full code:
import json
import sys
key = ['1']
myData = [
{
"id": 1,
"modifiedBy": "admin",
"fields": {
"Application": "1",
"Endtermin": 23011990
}
},
{
"id": 2,
"modifiedBy": "admin",
"fields": {
"Application": "2",
"Endtermin": 11021990
}
}
]
# delete json objects.
myData2 = [x for x in myData if x['fields']['Application'] not in key]
print(myData2)

Only getting string while iterating through json data

JSON:
{
"status": "success",
"data": {
"9": {
"1695056": {
"id": "1695056",
[...]
},
"csevents": {
"2807": {
"id": "2807",
"startdate": "2019-01-24 18:45:00",
"service_texts": [],
"eventTemplate": "1"
},
"2810": {
"id": "2810",
"startdate": "2019-01-31 18:45:00",
"service_texts": [],
"eventTemplate": "1"
}
}
},
"1695309": {
"id": "1695309",
[...]
},
"csevents": {
"3601": {
"id": "3601",
"startdate": "2019-05-17 18:45:00",
"service_texts": [],
"eventTemplate": "1"
}
I try to get the members from "csevents" ("2807", "2810", 3601") with python. Problem is that i don't know the IDs in "9" ("1695056", "1695309") while coding.
So i tried to iterate through "9" and then through "csevents" but if i iterate through "9" i only get a string so i can't iterate through "csevents" anymore.
Python:
for whatever in json_object['data']['9']:
for id in whatever['csevents']:
print(id)
So that doesn't work. Does anybody know how I can solve that?
Thanks
Had to clean up your JSON string to get it to work, but looking at your solution is seems like you're iterating directly from your dict, what you should be using is .items() or .values():
for key, value in json_object['data']['9'].items():
# We can use .keys() here since we only need the IDs from csevents
csevent_keys = list(value['csevents'].keys())
print(csevent_keys)
# Output
['2807', '2810']
['3601']

Flattening an array in a JSON object

I have a JSON object which I want to flatten before exporting it to CSV. I'd like to use the flatten_json module for this.
My JSON input looks like this:
{
"responseStatus": "SUCCESS",
"responseDetails": {
"total": 5754
},
"data": [
{
"id": 1324651
},
{
"id": 5686131
},
{
"id": 2165735
},
{
"id": 2133256
}
]
}
Easy so far even for a beginner like me, but what I'm interesting in exporting is only the data array. So, I would think of this:
data_json = json["data"]
flat_json = flatten_json.flatten(data_json)
Which doesn't work, since data is an array, stored as a list in Python, not as a dictionary:
[
{
"id": 1324651
},
{
"id": 5686131
},
{
"id": 2165735
},
{
"id": 2133256
}
]
How should I proceed to feed the content of the data array into the flatten_json function?
Thanks!
R.
This function expects a ditionary, let's pass one:
flat_json = flatten_json.flatten({'data': data_json})
Output:
{'data_0_id': 1324651, 'data_1_id': 5686131, 'data_2_id': 2165735, 'data_3_id': 2133256}
You can choose the keys you want to ignore when you call the flatten method. For example, in your case, you can do the following.
flatten_json.flatten(dic, root_keys_to_ignore={'responseStatus', 'responseDetails'})
where dic is the original JSON input.
This will give as output:
{'data_0_id': 1324651, 'data_1_id': 5686131, 'data_2_id': 2165735, 'data_3_id': 2133256}

Value in dictionary changes when variable changes

Trying to grab certain values from a json file and then 're-create' a new json file (sort of like a conversion). In the code below. I do the following:
define function that returns an dictionary
for each item in json, if function returns results, add results to list located inside parentObj dictionary
oldFile.json:
{
"elements": [
{
"fieldValues": [
{
"id": "101",
"value": "John"
},
{
"id": "102",
"value": "Doe"
}
]
},
{
"fieldValues": [
{
"id": "101",
"value": "Jane"
},
{
"id": "102",
"value": "Doe"
}
]
}
]
}
file.py
import json
import os
output = {}
parentObj = {}
parentObj['entries'] = []
def grabVals(iCounter):
# legend is a pre-determined dictionary matching ids with names (like first/last)
for myKey in subResults['elements'][iCounter]['fieldValues']:
if myKey['id'] in legend:
if 'value' in myKey:
newEntry = {legend[myKey['id']]: myKey['value']}
output.update(newEntry) # first adds 'John', then 'Doe'
# sample output below; next iteration would be 'Jane Doe'
# {"First": "John", "Last": "Doe"}
return output
subResults = json.loads(oldFile.json)
formCount = len(subResults['elements']) # subResults is the json above file. Grab total number of entries
for counter in range(0, formCount):
if convertTime(formEntryStamp, formEntryID) == 'keep': # self defined function (returns keep or None)
parentObj['entries'].append(grabVals(counter))
else:
pass
export = json.dumps(parent_obj, indent=4, sort_keys=False) # create new json based of dictionary
f = open("finished.json", "w")
f.write(export)
f.close()
Expected data in finished.json
{
"entries": [
{
"First": "John",
"Last": "Doe"
},
{
"First": "Jane",
"Last": "Doe"
}
]
}
Actual data in finished.json:
{
"entries": [
{
"First": "Jane",
"Last": "Doe"
},
{
"First": "Jane",
"Last": "Doe"
}
]
}
My question: How do I permanently write to parentObj? When output is changed in the function, the value inside parentObj is overwritten with new value. Does this have something to do mututable/immutable objects? Please let me know any further clarification is required.
Related links are similar, but refer to lists, whereas my is an object/dictionary:
Link 1
Link 2
After doing some reading on mutation of objects in python (link here), the code below solved my problem. Similar to what Juanpa said in the comments, I mutated the variable that was being re-used in my function (output). I assume with the code below, I am creating a copy thus leaving the original untouched.
def grabVals(iCounter, output=None):
if output == None:
output = {}
for myKey in subResults['elements'][iCounter]['fieldValues']:
if myKey['id'] in legend:
if 'value' in myKey:
newEntry = {legend[myKey['id']]: myKey['value']}
output.update(newEntry)
return output

Categories

Resources