ra67052
ra67052

Reputation: 507

How to create multiple records (aka objects) in a JSON using a for loop

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

Answers (1)

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

Related Questions