skip to Main Content

I am calling the Giphy API using another wrapper API which returns a list of dictionaries. I am having hard times to serialize the data to return it to AJAX.

The data is returned as InlineResponse200 with three properties.
(docu)

The problem is that my view is not able to return the JSON properly:

# Traceback
[2020-06-23 14:58:54,086] log: ERROR - Internal Server Error: /get_gifs/
Traceback (most recent call last):
  File "C:UsersJonasAppDataLocalProgramsPythonPython38-32libsite-packagesdjangocorehandlersexception.py", line 34, in inner
    response = get_response(request)
  File "C:UsersJonasAppDataLocalProgramsPythonPython38-32libsite-packagesdjangocorehandlersbase.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:UsersJonasAppDataLocalProgramsPythonPython38-32libsite-packagesdjangocorehandlersbase.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:UsersJonasDesktopfinspherefinsphereblogviews.py", line 234, in get_gifs
    return JsonResponse(api_response.data[0])
  File "C:UsersJonasAppDataLocalProgramsPythonPython38-32libsite-packagesdjangohttpresponse.py", line 554, in __init__
    raise TypeError(
TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.
[23/Jun/2020 14:58:54] "POST /get_gifs/ HTTP/1.1" 500 17874

If I add safe=False it returns TypeError: Object of type Gif is not JSON serializable

I don’t get this since api_response.data[0] is a cristal clear dictionary.

Desired outcome: Get the Giphy object logged in the success function of Ajax.

AJAX

(function($) {
  $('#btnSearch').on('click', function(e) {
      var query = $('#search').val();
      console.log(query);
      e.preventDefault();
      $.ajax({
        type: 'post',
        async: true,
        url: '/get_gifs/',
        data: {
          'query': query,
          'csrfmiddlewaretoken': window.CSRF_TOKEN // from blog.html
        },
        success: function(response) {

        },
        error: function(xhr, status, error) {
          // shit happens friends!
        }
    });
  });
}(jQuery));

(Inserted my original -free- API key for reproduction)

Views.py

def get_gifs(request):

        # create an instance of the API class
        api_instance = giphy_client.DefaultApi()

        # API Key
        api_key = 'NGSKWrBqtIq1rFU1Ka11D879Y1u4Igia'

        # Search term
        q = request.POST.get('query')
        print(q)

        # Query parameters
        limit = 2
        offset = 0
        rating = 'g'
        lang = 'en'
        fmt = 'json'

        try:
            # Search Endpoint
            api_response = api_instance.gifs_search_get(api_key, q, limit=limit, offset=offset, rating=rating, lang=lang, fmt=fmt)
            pprint(api_response)
        except ApiException as e:
            print("Exception when calling DefaultApi->gifs_search_get: %sn" % e)

        return JsonResponse(api_response.data[0])

API fetched object (pprint api_response)

{'data': [{'bitly_gif_url': 'https://gph.is/g/EJWjdvN',
           'bitly_url': 'https://gph.is/g/EJWjdvN',
           'content_url': '',
           'create_datetime': None,
           'embed_url': 'https://giphy.com/embed/J0JGg6doLfmV0yZmIB',
           'featured_tags': None,
           'id': 'J0JGg6doLfmV0yZmIB',
           'images': {'downsized': {'height': '250',
                                    'size': '350582',
                                    'url': 'https://media3.giphy.com/media/J0JGg6doLfmV0yZmIB/giphy.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy.gif',
                                    'width': '478'},
                      'downsized_large': {'height': '250',
                                          'size': '350582',
                                          'url': 'https://media3.giphy.com/media/J0JGg6doLfmV0yZmIB/giphy.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy.gif',
                                          'width': '478'},
                      'preview_gif': {'height': '134',
                                      'size': '49623',
                                      'url': 'https://media3.giphy.com/media/J0JGg6doLfmV0yZmIB/giphy-preview.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy-preview.gif',
                                      'width': '256'}},
           'import_datetime': '2020-06-15 10:01:39',
           'is_anonymous': None,
           'is_community': None,
           'is_featured': None,
           'is_hidden': None,
           'is_indexable': None,
           'is_realtime': None,
           'is_removed': None,
           'is_sticker': False,
           'rating': 'g',
           'slug': 'MITEF-mitefarab-asc2020-J0JGg6doLfmV0yZmIB',
           'source': 'www.mitefarab.org',
           'source_post_url': 'www.mitefarab.org',
           'source_tld': '',
           'tags': None,
           'trending_datetime': '0000-00-00 00:00:00',
           'type': 'gif',
           'update_datetime': None,
           'url': 'https://giphy.com/gifs/MITEF-mitefarab-asc2020-J0JGg6doLfmV0yZmIB',
           'user': {'avatar_url': 'https://media2.giphy.com/avatars/MITEF/8FTlysEjtXzx.jpg',
                    'banner_url': '',
                    'display_name': 'MITEF Pan Arab',
                    'profile_url': 'https://giphy.com/MITEF/',
                    'twitter': None,
                    'username': 'MITEF'},
           'username': 'MITEF'},
          {'bitly_gif_url': 'https://gph.is/g/ZdxQQpP',
           'bitly_url': 'https://gph.is/g/ZdxQQpP',
           'content_url': '',
           'create_datetime': None,
           'embed_url': 'https://giphy.com/embed/hTJF0O4vDkJsUi1h8Q',
           'featured_tags': None,
           'id': 'hTJF0O4vDkJsUi1h8Q',
           'images': {'downsized': {'height': '480',
                                    'size': '310971',
                                    'url': 'https://media3.giphy.com/media/hTJF0O4vDkJsUi1h8Q/giphy.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy.gif',
                                    'width': '480'},                      
                      'preview': {'height': '480',
                                  'mp4': 'https://media3.giphy.com/media/hTJF0O4vDkJsUi1h8Q/giphy-preview.mp4?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy-preview.mp4',
                                  'mp4_size': '15536',
                                  'width': '480'},
                      'preview_gif': {'height': '480',
                                      'size': '22387',
                                      'url': 'https://media3.giphy.com/media/hTJF0O4vDkJsUi1h8Q/giphy-preview.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy-preview.gif',
                                      'width': '480'}},
           'import_datetime': '2019-07-19 22:27:40',
           'is_anonymous': None,
           'is_community': None,
           'is_featured': None,
           'is_hidden': None,
           'is_indexable': None,
           'is_realtime': None,
           'is_removed': None,
           'is_sticker': False,
           'rating': 'g',
           'slug': 'RecargaPay-cashback-recargapay-paguetudopelocelular-hTJF0O4vDkJsUi1h8Q',
           'source': 'www.recargapay.com.br',
           'source_post_url': 'www.recargapay.com.br',
           'source_tld': '',
           'tags': None,
           'trending_datetime': '0000-00-00 00:00:00',
           'type': 'gif',
           'update_datetime': None,
           'url': 'https://giphy.com/gifs/RecargaPay-cashback-recargapay-paguetudopelocelular-hTJF0O4vDkJsUi1h8Q',
           'user': {'avatar_url': 'https://media0.giphy.com/avatars/RecargaPay/msKTiPaVkvqd.png',
                    'banner_url': 'https://media0.giphy.com/headers/RecargaPay/kg023vdaAaWA.gif',
                    'display_name': 'RecargaPay',
                    'profile_url': 'https://giphy.com/RecargaPay/',
                    'twitter': None,
                    'username': 'RecargaPay'},
           'username': 'RecargaPay'}],
 'meta': {'msg': 'OK',
          'response_id': '65bc1664c2b17e3e4b60d88c736d0c6b5a39d682',
          'status': 200},
 'pagination': {'count': 2, 'offset': 0, 'total_count': 10}}

3

Answers


  1. Python has a built in function for converting dicts to json.

    import json
    
    data = api_response.data
    return render(request, json.dumps(data))
    

    If you use that in your return statement it should return json.

    Login or Signup to reply.
  2. render(request, template_name, context=None, content_type=None, status=None, using=None)
    

    render() Combines a given template with a given context dictionary
    and returns an HttpResponse object with that rendered text.

    You can either use Django defaults JsonResponse class or Django REST framework Response class to return JSON responses.

    from django.http import JsonResponse
    return JsonResponse(data=api_response.data)
    
    from rest_framework.response import Response
    return Response(data=api_response.data)
    

    tried it on the ipython shell and it works just fine.

    In [15]: response = Response(api_response.data[0])                                                                                                                              
    
    In [16]: response                                                                                                                                                               
    Out[16]: <Response status_code=200, "text/html; charset=utf-8">
    

    response.data gives me the serialized response.

    Login or Signup to reply.
  3. I go though your code everything is correct except return JsonResponse(api_response.data[0]) in your views

    JsonResponse:

    The first parameter, data, should be a dict instance. If the safe parameter is set to False, it can be any JSON-serializable object. official documentation link

    When you say

    1. safe=True

    return JsonResponse(api_response.data[0])
    
    TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.
    

    The error is obvious api_response.data[0] is not dict, see point 2 error

    2
    safe=False

    return JsonResponse(api_response.data[0], safe=False)
    TypeError: Object of type Gif is not JSON serializable
    

    The data api_response.data[0] you provide to JsonResponse is not a dict type object actually, that’s why you got error for first point.

    when you say safe=False JsonResponse is trying to serialize object but that object is not json serializable, you can trace-back error

    File "....PythonPython38libjsonencoder.py", line 179, in default
        raise TypeError(f'Object of type {o.__class__.__name__} '
    TypeError: Object of type Gif is not JSON serializable
    

    Can be followed the link to see which object can be Json serializable

    Coming back to your error.

    I don’t get this since api_response.data[0] is a cristal clear dictionary.

    type of api_response and api_response.data[0]

    type(api_response)
    <class 'giphy_client.models.inline_response_200.InlineResponse200'>
    type(api_response.data[0])
    <class 'giphy_client.models.gif.Gif'>
    

    You can follow for giphy_client documentation link for more-details

    Solution:

    result = api_response.data[0].to_dict()   ## NOTE to_dict function of giphy_client.models.gif.Gif
    
    return JsonResponse(result)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search