Mark
Mark

Reputation: 133

Create a Python class that I can serialize into a nested JSON object

I'm a very beginner with Python classes and JSON and I'm not sure I'm going in the right direction.

Basically, I have a web service that accepts a JSON request in a POST body like this:

{ "item" : 
     {
     "thing" : "foo",
     "flag" : true,
     "language" : "en_us"
     },
   "numresults" : 3
}

I started going down the route of creating a class for "item" like this:

class Item(object):
    def __init__:
        self.name = "item"

    @property
    def thing(self):
        return self.thing

    @thing.setter
    def thing(self, value):
        self.thing = value

    ...

So, my questions are:

  1. Am I going in the right direction?
  2. How do I turn the Python object into a JSON string?

I've found a lot of information about JSON in python, I've looked at jsonpickle, but I can't seem to create a class that ends up outputting the nested dictionaries needed.

EDIT: Thanks to Joran's suggestion, I stuck with a class using properties and added a method like this:

    def jsonify(self):
        return json.dumps({ "item" :  self.__dict__ }, indent=4)

and that worked perfectly.

Thanks everyone for your help.

Upvotes: 3

Views: 4686

Answers (3)

Martijn Pieters
Martijn Pieters

Reputation: 1124738

Take a look at the colander project; it let's you define an object-oriented 'schema' that is easily serializable to and from JSON.

import colander

class Item(colander.MappingSchema):
    thing = colander.SchemaNode(colander.String(),
                                validator=colander.OneOf(['foo', 'bar']))
    flag = colander.SchemaNode(colander.Boolean())
    language = colander.SchemaNode(colander.String()
                                   validator=colander.OneOf(supported_languages)

class Items(colander.SequenceSchema):
    item = Item()

Then load these from JSON:

items = Items().deserialize(json.loads(jsondata))

and colander validates the data for you, returning a set of python objects that then can be acted upon.

Alternatively, you'd have to create specific per-object handling to be able to turn Python objects into JSON structures and vice-versa.

Upvotes: 1

Jonathan Vanasco
Jonathan Vanasco

Reputation: 15690

The colander and dict suggestions are both great.

I'd just add that you should step back for a moment and decide how you'll use these objects.
A potential problem with this general approach is that you'll need a list or function or some other mapping to decide which attributes are exported. ( you see this in the colander definition and the jsonify definition ).

You might want this behavior - or you might not.

The sqlalchemy project for example, has classes which are defined with the field names are characteristics like ion colander. but the objects themselves store a lot of ancillary data relating to the database and db connection.

in order to get to just the underlying field data that you care about , you need to either access a private internal dict that wraps the data, or query the class for the mapped columns :

def columns_as_dict(self):
    return dict((col.name, getattr(self, col.name)) for col in sqlalchemy_orm.class_mapper(self.__class__).mapped_table.c)

i don't mean to overcomplicate this - i just want to suggest that you think about exactly how you're likely to use these objects. if you only want the same info out of your object that you put in it -- then a simple solution is fine. but if these objects are going to have some other sort of 'private' data , you might need to maintain some distinction between the different types of information.

Upvotes: 0

Joran Beasley
Joran Beasley

Reputation: 114088

just add one method to your class that returns a dictionary

def jsonify(self):
    return { 'Class Whatever':{
              'data1':self.data1,
               'data2':self.data2,
               ...
                               }

     }

and call your tojson function on the result ... or call it before your return to just return a json result...

Upvotes: 1

Related Questions