2

I try to store in Django session the following pretty much arbitrary class:

class QuizInfo:
    def __init__(self):
        self.i_active_question = INVALID_PQA_ID  # integer
        self.sequence = []

In turn, each item of QuizInfo.sequence list is an instance of AnsweredQuestion:

class AnsweredQuestion:
    def __init__(self, i_question, i_answer):
        self.i_question = i_question
        self.i_answer = i_answer

I try to store such a data structure in HttpRequest.session like the following:

qi = QuizInfo()
qi.i_active_question = 5  # e.g.
qi.sequence.append(AnsweredQuestion(1, 2))  # e.g.
qi.sequence.append(AnsweredQuestion(3, 4))  # e.g.
quiz_id = 7  # e.g.
request.session['quiz_infos'] = {quiz_id : qi}

So request.session['quiz_infos'] is a dictionary of int keys and QuizInfo values.

I get the following error:

Traceback:

File "C:\Users\Sarge\Envs\PqaWeb1\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\Sarge\Envs\PqaWeb1\lib\site-packages\django\utils\deprecation.py" in __call__
  93.             response = self.process_response(request, response)

File "C:\Users\Sarge\Envs\PqaWeb1\lib\site-packages\django\contrib\sessions\middleware.py" in process_response
  58.                             request.session.save()

File "C:\Users\Sarge\Envs\PqaWeb1\lib\site-packages\django\contrib\sessions\backends\db.py" in save
  83.         obj = self.create_model_instance(data)

File "C:\Users\Sarge\Envs\PqaWeb1\lib\site-packages\django\contrib\sessions\backends\db.py" in create_model_instance
  70.             session_data=self.encode(data),

File "C:\Users\Sarge\Envs\PqaWeb1\lib\site-packages\django\contrib\sessions\backends\base.py" in encode
  96.         serialized = self.serializer().dumps(session_dict)

File "C:\Users\Sarge\Envs\PqaWeb1\lib\site-packages\django\core\signing.py" in dumps
  87.         return json.dumps(obj, separators=(',', ':')).encode('latin-1')

File "c:\programs\python37\Lib\json\__init__.py" in dumps
  238.         **kw).encode(obj)

File "c:\programs\python37\Lib\json\encoder.py" in encode
  199.         chunks = self.iterencode(o, _one_shot=True)

File "c:\programs\python37\Lib\json\encoder.py" in iterencode
  257.         return _iterencode(o, 0)

File "c:\programs\python37\Lib\json\encoder.py" in default
  179.         raise TypeError(f'Object of type {o.__class__.__name__} '

Exception Type: TypeError at /
Exception Value: Object of type QuizInfo is not JSON serializable

How to make the data structure JSON-serializable?

I saw the other questions, however, the answers there mostly suggest to implement a method to pass as a parameter. But where to do this in Django?

Serge Rogatch
  • 13,865
  • 7
  • 86
  • 158

2 Answers2

0

Use __dict__ to change that into a dictionary. In your case though you have nested objects which also needs to be converted to dictionaries. This can be found in jsbueno answer here. Basically you have to iterate over your object to check for nested objects like so,

def my_dict(obj):
   if not  hasattr(obj,"__dict__"):
       return obj
   result = {}
   for key, val in obj.__dict__.items():
       if key.startswith("_"):
           continue
       element = []
       if isinstance(val, list):
           for item in val:
               element.append(my_dict(item))
       else:
           element = my_dict(val)
       result[key] = element
   return result

Edit:

Then you can dump the result to a string like so,

import json

json.dumps(result)

Hope this helps!

devdob
  • 1,404
  • 12
  • 13
0

Here is a possible solution.

Django's serializers are handy, when it comes to serializing/deserializing data.

You might throw an eye to this as well. Check out also deserialization.