Create multiple json objects by using for loop
Question:
I’m in the process of creating a billing system and need to output some data from my API. I want to return the data as JSON, but i’m only getting one of the db entries in my output, even though there is multiple. I strongly assume that im overwriting my earlier entry.
Current output is:
{
"id":2,
"status":"active",
"usage_type":"metered",
"amount":0,
"city":"Parkinson",
"country":"UK",
"line1":"Silverway 30",
"postal_code":"4450",
"state":"state",
"card_brand":"visa",
"card_country":"US",
"card_exp_month":3,
"card_exp_year":2025,
"card_last4":"4242"
}
But it’s missing the "id":1
from my db, which I assume is because im overwriting the earlier stuff.
The output I would like to have should look like this:
{
"id":1 {
"status":"active",
"usage_type":"metered",
"amount":0,
"city":"Parkinson",
"country":"UK",
"line1":"Silverway 1",
"postal_code":"0030",
"state":"state",
"card_brand":"visa",
"card_country":"US",
"card_exp_month":3,
"card_exp_year":2025,
"card_last4":"4242"
},
"id":2 {
"status":"active",
"usage_type":"metered",
"amount":0,
"city":"Parkinson",
"country":"UK",
"line1":"Silverway 20",
"postal_code":"0330",
"state":"state",
"card_brand":"visa",
"card_country":"US",
"card_exp_month":3,
"card_exp_year":2025,
"card_last4":"4242"
},
My current code:
@api_view(['GET',])
@permission_classes([IsAuthenticated])
def get_billing(request):
"""
List current billing options
"""
if request.method == 'GET':
data = Customer.objects.filter(user=request.user)
jsondata = {}
for subscription in data:
get_subscription = stripe.Subscription.retrieve(subscription.subscription_id)
get_payment = stripe.PaymentMethod.retrieve(subscription.payment_method)
jsondata["id"] = subscription.pk
jsondata["status"] = get_subscription['status']
jsondata["usage_type"] = get_subscription['plan']['usage_type']
jsondata["amount"] = get_subscription['plan']['amount']
jsondata['city'] = get_payment['billing_details']['address']['city']
jsondata['country'] = get_payment['billing_details']['address']['country']
jsondata['line1'] = get_payment['billing_details']['address']['line1']
jsondata['postal_code'] = get_payment['billing_details']['address']['postal_code']
jsondata['state'] = get_payment['billing_details']['address']['state']
jsondata['card_brand'] = get_payment['card']['brand']
jsondata['card_country'] = get_payment['card']['country']
jsondata['card_exp_month'] = get_payment['card']['exp_month']
jsondata['card_exp_year'] = get_payment['card']['exp_year']
jsondata['card_last4'] = get_payment['card']['last4']
json_data = json.dumps(jsondata)
return Response(jsondata, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
What am I doing wrong? Let me know if I need to provide more info. Thanks!
Answers:
Here is more of a working example. This makes a map of objects. If could also use a list, but that highly depends on your use case:
data = [
{
"pk": 1,
"status" : "valid",
"plan" : "PayAsYouGo"
},
{
"pk": 2,
"status": "invalid",
"plan": "PayAsYouGo"
},
]
jsondata = {}
for subscription in data:
json = {
"status" : subscription['status'],
"usage": subscription['plan']
}
jsondata[subscription['pk']] = json
print(jsondata)
Output:
{1:
{
'status': 'valid',
'usage': 'PayAsYouGo'
},
2: {
'status': 'invalid',
'usage': 'PayAsYouGo'
}
}
You probably want to return a list. It’s often a good idea to wrap a list in a dict, in case you want to extend later with other metadata, like pagination or whatever. Hence the {‘items’: […]}
# ...
customers = Customer.objects.filter(user=request.user)
items = []
for customer in customers:
subscription = stripe.Subscription.retrieve(customer.subscription_id)
payment = stripe.PaymentMethod.retrieve(customer.payment_method)
items.append({
'id': customer.pk,
'status': subscription['status'],
# ... the rest of your data ...
})
# Next line does nothing...
# json_data = json.dumps(jsondata)
return Response({'items': items}) # Status is 200 by default
I’m in the process of creating a billing system and need to output some data from my API. I want to return the data as JSON, but i’m only getting one of the db entries in my output, even though there is multiple. I strongly assume that im overwriting my earlier entry.
Current output is:
{
"id":2,
"status":"active",
"usage_type":"metered",
"amount":0,
"city":"Parkinson",
"country":"UK",
"line1":"Silverway 30",
"postal_code":"4450",
"state":"state",
"card_brand":"visa",
"card_country":"US",
"card_exp_month":3,
"card_exp_year":2025,
"card_last4":"4242"
}
But it’s missing the "id":1
from my db, which I assume is because im overwriting the earlier stuff.
The output I would like to have should look like this:
{
"id":1 {
"status":"active",
"usage_type":"metered",
"amount":0,
"city":"Parkinson",
"country":"UK",
"line1":"Silverway 1",
"postal_code":"0030",
"state":"state",
"card_brand":"visa",
"card_country":"US",
"card_exp_month":3,
"card_exp_year":2025,
"card_last4":"4242"
},
"id":2 {
"status":"active",
"usage_type":"metered",
"amount":0,
"city":"Parkinson",
"country":"UK",
"line1":"Silverway 20",
"postal_code":"0330",
"state":"state",
"card_brand":"visa",
"card_country":"US",
"card_exp_month":3,
"card_exp_year":2025,
"card_last4":"4242"
},
My current code:
@api_view(['GET',])
@permission_classes([IsAuthenticated])
def get_billing(request):
"""
List current billing options
"""
if request.method == 'GET':
data = Customer.objects.filter(user=request.user)
jsondata = {}
for subscription in data:
get_subscription = stripe.Subscription.retrieve(subscription.subscription_id)
get_payment = stripe.PaymentMethod.retrieve(subscription.payment_method)
jsondata["id"] = subscription.pk
jsondata["status"] = get_subscription['status']
jsondata["usage_type"] = get_subscription['plan']['usage_type']
jsondata["amount"] = get_subscription['plan']['amount']
jsondata['city'] = get_payment['billing_details']['address']['city']
jsondata['country'] = get_payment['billing_details']['address']['country']
jsondata['line1'] = get_payment['billing_details']['address']['line1']
jsondata['postal_code'] = get_payment['billing_details']['address']['postal_code']
jsondata['state'] = get_payment['billing_details']['address']['state']
jsondata['card_brand'] = get_payment['card']['brand']
jsondata['card_country'] = get_payment['card']['country']
jsondata['card_exp_month'] = get_payment['card']['exp_month']
jsondata['card_exp_year'] = get_payment['card']['exp_year']
jsondata['card_last4'] = get_payment['card']['last4']
json_data = json.dumps(jsondata)
return Response(jsondata, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
What am I doing wrong? Let me know if I need to provide more info. Thanks!
Here is more of a working example. This makes a map of objects. If could also use a list, but that highly depends on your use case:
data = [
{
"pk": 1,
"status" : "valid",
"plan" : "PayAsYouGo"
},
{
"pk": 2,
"status": "invalid",
"plan": "PayAsYouGo"
},
]
jsondata = {}
for subscription in data:
json = {
"status" : subscription['status'],
"usage": subscription['plan']
}
jsondata[subscription['pk']] = json
print(jsondata)
Output:
{1:
{
'status': 'valid',
'usage': 'PayAsYouGo'
},
2: {
'status': 'invalid',
'usage': 'PayAsYouGo'
}
}
You probably want to return a list. It’s often a good idea to wrap a list in a dict, in case you want to extend later with other metadata, like pagination or whatever. Hence the {‘items’: […]}
# ...
customers = Customer.objects.filter(user=request.user)
items = []
for customer in customers:
subscription = stripe.Subscription.retrieve(customer.subscription_id)
payment = stripe.PaymentMethod.retrieve(customer.payment_method)
items.append({
'id': customer.pk,
'status': subscription['status'],
# ... the rest of your data ...
})
# Next line does nothing...
# json_data = json.dumps(jsondata)
return Response({'items': items}) # Status is 200 by default