Reputation: 133
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:
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
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
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
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