Reputation: 101494
RHEL 6.5, python 2.6.6
I'm trying to write decoded messages in to a MongoDB collection. The "decoded message" is received in the form of a dictionary. Within that dictionary the keys are all strings, and the values can be strings, integers, datetime.time
, datetime.datetime
, or Decimal
types.
I've written an on_message
function which is called with a parameter context
contining the dictionary to be saved to MongoDB. I've also written a lambda to convert some types that aren't JSON serializeable.
dthandler = lambda obj: (
str(obj)
if isinstance(obj, Decimal)
or isinstance(obj, datetime.time)
else None
)
class Decoder(decoder.base.Base):
# ...
def on_message(self, context, payload):
""" Write decoded message to DB
"""
msg = dict(context)
try:
print self.mongo_coll
# This is just a test to confirm the connection is established properly.
# I am able to see this value in the DB using Robomongo after this insert
# call
self.mongo_coll.insert({'foo': 'john'})
x = json.dumps(context, default=dthandler)
print x
self.mongo_coll.insert(x)
except errors.OperationFailure as op:
print "Operation Exception"
except Exception as ex:
print "Serialization Exception (mongo/write.py)"
exs = str(ex)
print exs
print '^^^^^'
The call to print self.mongo_coll
yields:
Collection(Database(MongoClient('localhost', 27017), u'itch'), u'test')
the call to print x
yields (all results are similar):
{"msg-type-name": "AddOrderAttributed", "next-expect-msg-seq-num": 3023982, "mold-num-msgs": 34, "recv-timestamp": null, "ord-ref-num": 4365786, "msg-type": "F", "recv-time-nano": 2523000, "raw-price": 781200, "msg-seq-num": 3023981, "shares": 100, "buy-sell": "B", "stock": "RNR", "attribution": "RBCM", "timestamp": "09:30:00.002189", "price": "78.12", "tracking-number": 1, "recv-time-sec": 1419431400, "msg-size": 40, "mold-seq-num": 3023959, "stock-locate": 6281, "mold-session": "000006896B", "msg-payload": "00 28 46 18 89 00 01 1f 1a ce fb 57 59 00 00 00 00 00 42 9d da 42 00 00 00 64 52 4e 52 20 20 20 20 20 00 0b eb 90 52 42"}
However the call to self.mongo_coll.insert(x)
yields an Exception
:
Serialization Exception (mongo/write.py)
'str' object does not support item assignment
^^^^^
I'm quite confused especially given that there is no mention of str
in my code, except in my exception handler and within dthandler
.
What am I doing wrong?
Per edits and answers, I've made a couple modifications. Alas, I'm still having trouble. Here's the new code:
def on_message(self, context, payload):
""" Write decoded message to DB
"""
msg = dict(context)
try:
print self.mongo_coll
self.mongo_coll.insert(msg)
x = json.dumps(context, default=dthandler)
print self.mongo_coll
print x
self.mongo_coll.insert(msg)
except errors.OperationFailure as op:
print "Operation Exception"
except Exception as ex:
traceback.print_exc()
print "Serialization Exception (mongo/write.py)"
exs = str(ex)
print exs
print '^^^^^'
...and the output:
Collection(Database(MongoClient('localhost', 27017), u'itch'), u'test')
Traceback (most recent call last):
File "./decoder/mongo/write.py", line 69, in on_message
self.mongo_coll.insert(msg)
File "/usr/lib64/python2.6/site-packages/pymongo/collection.py", line 409, in insert
gen(), check_keys, self.uuid_subtype, client)
InvalidDocument: Cannot encode object: Decimal('65.1')
Serialization Exception (mongo/write.py)
Cannot encode object: Decimal('65.1')
^^^^^
Upvotes: 2
Views: 6293
Reputation: 1879
I had the same issue like you, and I found this solution:
import json
valuestr = json.dumps(myclass, default=lambda x:x.__dict__)
value = json.loads(valuestr) # <-- returned data is not string
db.posts.insert(value)
Upvotes: 0
Reputation:
I can't tell if this was resolved or not. But I was having the same issue, so I'll post my solution here to help others.
I'm working off this example.
Problem code:
# insert the student object into MongoDB
object_id = student_collection.insert(a_student.to_JSON())
Solution:
object_id = student_collection.insert({"email": "[email protected]", "name": {"first": "Daniel", "last": "Watrous"}, "major": "Electrical Engineering"})
Even though we're saying "to_JSON()" here, the insert method gets confused and will throw an error when it goes to execute. Because it's getting a string, it thinks it's a string, rather than JSON.
I'm using Python 3.5. The version might have something to do with it too. Maybe it worked with Python 2.7.
Hopefully this will help someone.
Upvotes: 1
Reputation: 23098
Your line here
x = json.dumps(context, default=dthandler)
Makes x
a string. Simply use
self.mongo_coll.insert(msg)
It's better not to insert context
directly, rather insert msg
(which is a dict
, not a context object).
Upvotes: 2