1

I have a JSON file hosted locally in my Django directory. It is fetched from that file to a view in views.py, where it is read in like so:

def Stops(request):
   json_data = open(finders.find('JSON/myjson.json'))
   data1 = json.load(json_data)  # deserialises it
   data2 = json.dumps(data1)  # json formatted string
   json_data.close()
   return JsonResponse(data2, safe=False)

Using JsonResponse without (safe=False) returns the following error:

TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.

Similarly, using json.loads(json_data.read()) instead of json.load gives this error:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

This is confusing to me - I have validated the JSON using an online validator. When the JSON is sent to the frontend with safe=False, the resulting object that arrives is a string, even after calling .json() on it in javascript like so:

fetch("/json").then(response => {
     return response.json();
     }).then(data => {
     console.log("data ", data); <---- This logs a string to console
...

However going another step and calling JSON.parse() on the string converts the object to a JSON object that I can use as intended

       data = JSON.parse(data);
       console.log("jsonData", data); <---- This logs a JSON object to console

But this solution doesn't strike me as a complete one.

At this point I believe the most likely thing is that there is something wrong with the source JSON - (in the file character encoding?) Either that or json.dumps() is not doing what I think it should, or I am not understanding the Django API's JSONresponse function in a way I'm not aware of...

I've reached the limit of my knowledge on this subject. If you have any wisdom to impart, I would really appreciate it.

EDIT: As in the answer below by Abdul, I was reformatting the JSON into a string with the json.dumps(data1) line

Working code looks like:

def Stops(request):
   json_data = open(finders.find('JSON/myjson.json'))
   data = json.load(json_data)  # deserialises it
   json_data.close()
   return JsonResponse(data, safe=False)  # pass the python object here
Eugene Egan
  • 25
  • 1
  • 6

1 Answers1

0

Let's see the following lines of your code:

json_data = open(finders.find('JSON/myjson.json'))
data1 = json.load(json_data)  # deserialises it
data2 = json.dumps(data1)  # json formatted string

You open a file and get a file pointer in json_data, parse it's content and get a python object in data1 and then turn it back into a JSON string and store it into data2. Somewhat redundant right? Next you pass this JSON string to JsonResponse which will further try to serialize it into JSON!! Meaning you then get a string inside a string in JSON.

Try the following code instead:

def Stops(request):
   json_data = open(finders.find('JSON/myjson.json'))
   data = json.load(json_data)  # deserialises it
   json_data.close()
   return JsonResponse(data, safe=False)  # pass the python object here

Note: function names in python should ideally be in snake_case not PascalCase, hence instead of Stops you should use stops. See PEP 8 -- Style Guide for Python Code

Abdul Aziz Barkat
  • 19,475
  • 3
  • 20
  • 33
  • 1
    Yes indeed, you caught it! Thanks a million for taking the time to help out with my silly error (I'll work on making smarter errors in future!) – Eugene Egan Jul 16 '21 at 13:46