Reputation: 507
Python noob here. I'm trying to create a python script to auto-generate a JSON with multiple itemAvailability records (aka Objects) using a for loop to generate them, the JSON message is structured and cardinality are as follows:
messageHeader[1]
-itemId [1]
--itemAvailability [1-*]
The itemAvailability record lets the system know when the item is available and I'm trying to create a loop so that it will create random itemAvailability times for the next 28 days. I've tried looking online but cannot see anything that solves this particular problem, I have tested the functions and for loop in isolation so know they work but cannot get the for loop to create more than one itemAvailability record in a JSON. I can get a one to one conversion but as soon as I try any form of looping it blows up or does not create more than one itemAvailability record. I'm struggling to see anything online for being able to create JSON's using python with multiple objects of the same type, the code so far I have:
import json
from datetime import datetime, timedelta
import math
from random import randrange
def starttimestamp(curr, delta):
start = datetime.min + math.ceil((curr - datetime.min) / delta) * delta
formatted = start.strftime("%Y-%m-%dT%H:%M:%SZ")
return formatted
def endtimestamp(curr, delta):
end = datetime.min + math.ceil((curr - datetime.min) / delta) * delta + timedelta(minutes=randrange (30,600,30))
formatted = end.strftime("%Y-%m-%dT%H:%M:%SZ")
return formatted
timestamp = datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
data = {'messageId': "theId", 'transId': 'theOtherId',
'createdTimestamp': timestamp, 'itemList': [{
'itemId': "I"}]}
today = datetime.now()
next_day = timedelta(days = 1)
date_counter = 0
for days in range(0, 28):
date_counter += 1
today += next_day
curr = today
data['itemList'][0]['itemAvailability'] = {
'startTimestamp': starttimestamp(curr, timedelta(minutes=30)),
'endTimestamp' : endtimestamp(curr, timedelta(minutes=30))}
with open(r'C:\\Somewhere.json', 'w') as outfile:
json.dump(data, outfile)
What I get is this:
{
"messageId": "theId",
"transId": "theOtherId",
"createdTimestamp": "2019-04-08T00:32:47Z",
"itemList": [{
"itemId": "I",
"itemAvailability": {
"startTimestamp": "2019-05-06T01:00:00Z",
"endTimestamp": "2019-05-06T06:30:00Z",
"availability": "A"
}
}]
}
But what I want is something like this:
{
"messageId": "theId",
"transId": "theOtherId",
"createdTimestamp": "2019-04-08T00:32:47Z",
"itemList": [{
"itemId": "I",
"itemAvailability": {
"startTimestamp": "2019-05-06T01:00:00Z",
"endTimestamp": "2019-05-06T06:30:00Z",
"availability": "A",
"itemAvailability": {
"startTimestamp": "2019-05-06T01:00:00Z",
"endTimestamp": "2019-05-06T06:30:00Z",
"availability": "A",
"itemAvailability": {
"startTimestamp": "2019-05-06T01:00:00Z",
"endTimestamp": "2019-05-06T06:30:00Z",
"availability": "A",
"itemAvailability": {
"startTimestamp": "2019-05-06T01:00:00Z",
"endTimestamp": "2019-05-06T06:30:00Z",
"availability": "A",
"itemAvailability": {
"startTimestamp": "2019-05-06T01:00:00Z",
"endTimestamp": "2019-05-06T06:30:00Z",
"availability": "A",
"itemAvailability": {
"startTimestamp": "2019-05-06T01:00:00Z",
"endTimestamp": "2019-05-06T06:30:00Z",
"availability": "A"
}
}
]
}
Upvotes: 3
Views: 1476
Reputation: 7887
A json object is just a dictionary
or hash table. This means that EVERY key must be unique.
For Example:
d[1] = 'a' # d = {1: 'a'}
d[1] = 'b' # d = {1: 'b'} - Note that the value for 1 is overridden.
So from your code:
for days in range(0, 28):
date_counter += 1
today += next_day
curr = today
# Note the key for your `data` dictionary never changes.
# Your code is always writing to the same key: ['itemList'][0]['itemAvailability'].
data['itemList'][0]['itemAvailability'] = {
'startTimestamp': starttimestamp(curr, timedelta(minutes=30)),
'endTimestamp' : endtimestamp(curr, timedelta(minutes=30))}
To solve this, and meet your desired output
import json
from datetime import datetime, timedelta
import math
from random import randrange
def starttimestamp(curr, delta):
start = datetime.min + math.ceil((curr - datetime.min) / delta) * delta
formatted = start.strftime("%Y-%m-%dT%H:%M:%SZ")
return formatted
def endtimestamp(curr, delta):
end = datetime.min + math.ceil((curr - datetime.min) / delta) * delta + timedelta(minutes=randrange (30,600,30))
formatted = end.strftime("%Y-%m-%dT%H:%M:%SZ")
return formatted
timestamp = datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
data = {'messageId': "theId", 'transId': 'theOtherId',
'createdTimestamp': timestamp, 'itemList': [{
'itemId': "I"}]}
today = datetime.now()
next_day = timedelta(days = 1)
date_counter = 0
# We need the ability to move a pointer down the dictionary.
temp_data = data['itemList'][0]
for days in range(0, 28):
date_counter += 1
today += next_day
curr = today
temp_data['itemAvailability'] = { # Create the dict for our current level
'startTimestamp': starttimestamp(curr, timedelta(minutes=30)),
'endTimestamp' : endtimestamp(curr, timedelta(minutes=30)),
'availability': 'A',
'itemAvailability': dict()
}
temp_data = temp_data['itemAvailability'] # Move the pointer down one level
print(json.dumps(data, indent=4))
Note: I do not recommend nesting your payload this way. If every object is the same then you shouldn't nest it but instead list
it.
date_counter = 0
data['itemList'][0]['itemAvailability'] = list()
for days in range(0, 28):
date_counter += 1
today += next_day
curr = today
data['itemList'][0]['itemAvailability'].append({
'startTimestamp': starttimestamp(curr, timedelta(minutes=30)),
'endTimestamp' : endtimestamp(curr, timedelta(minutes=30)),
'availability': 'A',
})
print(json.dumps(data, indent=4))
Upvotes: 1