3

I have tried to have a decent business layer that is server side. Less work possible for each new business class to be stored in the database.

However, it doesn't perform the convertion to json very well. It works for simple python object, using json.dumps(self.__dict__). But a list of simple python objects does not serialize to json very well.

When performing a json serialization of a list I try to return json.dumps([x.to_json() for x in self.my_list_items]) but it outputs additionnal double quotes, and \" for each item in the list: ["{\"completed\": 0, \"id\": 1, \"name\": \"labelOne\"}", "{\"completed\": 0, \"id\": 2, \"name\": \"Label2\"}"]

This is the code I use:

class JSONizable(object):
    def to_json(self):
        return json.dumps(self.__dict__)    

class Task(JSONizable):
    def __init__(self):
        self.id = -1
        self.name = "new task"
        self.completed = 1

    def load_sql(self, sql):
        #do things

class Tasks(JSONizable):
    def __init__(self):
        self.tasks=[]

    def load_sql(self,sql):
        #do things

    def to_json(self):
       return json.dumps([x.to_json() for x in self.tasks]) # things go bad here

Could you suggest a more pythonic way to perform json serialization for python object, when such object contains lists of items ?

3
  • You're encoding to JOSN, then dumping the JSON. I think you just want: return json.dumps(self.tasks) Commented Aug 7, 2013 at 8:31
  • @ckhan, if i do that, the json module claims that task is not json serializable. Commented Aug 7, 2013 at 8:33
  • See the docs on writing a custom JSON encoder: docs.python.org/2/library/json.html#json.JSONEncoder Commented Aug 7, 2013 at 8:35

4 Answers 4

2

Actually the only working solution to this is bit ugly and IMHO unpythonic.

The solution is to extend JSONEncoder overriding its default() method:

import json

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if not isinstance(obj, Task):
            return super(CustomEncoder, self).default(obj)
        return obj.__dict__

json.dumps(list_of_tasks, cls=CustomEncoder)
Sign up to request clarification or add additional context in comments.

Comments

2

Combining njzk2's and freakish's answers, I ended up with a solution that does the job nicely.

import json
import database

class JSONizable(object):
    def to_json(self):
        return json.dumps(self.to_serializable())
    def to_serializable(self):
        return  self.__dict__

class Task(JSONizable):
    def __init__(self):
        self.id = -1
        self.name = "new task"
        self.completed = 1

    def load_sql(self, sql):
        #...

class Tasks(JSONizable):
    def __init__(self):
        self.tasks=[]

    def load_sql(self,sql):
        #...

    def to_serializable(self):
        return [x.to_serializable() for x in self.tasks]

def get_json_tasks():
    db = database.db
    tasks = Tasks()
    tasks.load_sql(db.get_sql_tasks())
    return tasks.to_json()

It outputs in proper Json format: [{"completed": 0, "id": 1, "name": "labelOne"}, {"completed": 0, "id": 2, "name": "labelTwo"}, {"completed": 0, "id": 3, "name": "LabelThree"}] just like I needed.

1 Comment

+1: great idea. Just be careful about self.__dict__. It might not be serializable.
1

The problem is that you are serializing twice. Once in x.to_json() and second time when you create a list and serialize it in Tasks.to_json. I suggest you convert to dicts instead of JSON:

class Task(JSONizable):
    def to_serializable(self):
        return {
            # some JSON serializable data here
            "id": self.id,
            "name": self.name,
            "completed": self.completed
        }

class Tasks(JSONizable):
    def to_serializable(self):
        return [x.to_serializable() for x in self.tasks]

and then when you have an instance of Tasks class:

TasksInstance = Tasks()
json.dumps(TasksInstance.to_serializable())

By the way: using self.__dict__ might not work anyway, since an instance of JSONizable may contain non-serializable attributes, for example an instance of another class.

Comments

1

your to_json formats as json. returning the __dict__ is sufficient :

class JSONizable(object):
    def to_json(self):
        return self.__dict__

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.