Philip
Philip

Reputation: 3500

(De-)Serialization with PyMongo and JSON

In a project that keeps data inside a MongoDB and that also exposes some data via a (read-only) RESTish JSON API, dealing with Python objects requires some extra work. Serialization and Deserializing only works automatically when dealing with dicts or other simple types like string.

So for the JSON serialization, I came up with this:

import json

class Encoder(json.JSONEncoder):
  def default(self, obj):
    if isinstance(obj, Foo):
      return {'bar': obj.bar}
    return json.JSONEncoder.fault(self, obj)

class Foo:
  def __init__(self, bar):
    self.bar = bar

foo = Foo("bar")
encoded = json.dumps(tokens, cls=Encoder)

This works pretty well. But now I would like to insert foo into MongoDB:

db.foobars.insert(foo)

Obviously this doesn't work:

Traceback (most recent call last):
  ...
    db.foobars.insert(foo)
  File "/usr/local/lib/python2.7/dist-packages/pymongo/collection.py", line 351, in insert
    docs = [self.__database._fix_incoming(doc, self) for doc in docs]

How can this made working?

Upvotes: 2

Views: 512

Answers (1)

alecxe
alecxe

Reputation: 473863

By calling db.foobars.insert(foo), you are trying to insert an instance of a Foo class. insert method allows only a dict, or a list of dicts as the first argument. That's why you are seeing an error:

File "/home/alexander/.virtualenvs/so/local/lib/python2.7/site-packages/pymongo/collection.py", line 351, in insert docs = [self.__database._fix_incoming(doc, self) for doc in docs] TypeError: iteration over non-sequence

One way to fix this is to load encoded string back into dict:

foo = Foo("bar")
encoded = json.dumps(foo, cls=Encoder)
db.foobars.insert(json.loads(encoded))

Or, use __dict__:

db.foobars.insert(foo.__dict__)

Hope that helps.

Upvotes: 1

Related Questions