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!

Asked By: Super doe

||

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'
     }
}
Answered By: user2199860

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
Answered By: Johan Schiff
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.