The Python Oracle

TypeError: ObjectId('') is not JSON serializable

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Beneath the City Looping

--

Chapters
00:00 Question
01:35 Accepted answer (Score 164)
01:59 Answer 2 (Score 211)
02:18 Answer 3 (Score 51)
03:36 Answer 4 (Score 48)
04:06 Thank you

--

Full question
https://stackoverflow.com/questions/1658...

Accepted answer links:
[JSONEncoder]: http://docs.python.org/2/library/json.ht...

Answer 2 links:
[Pymongo]: http://api.mongodb.org/python/current/in...
[json_util]: http://api.mongodb.org/python/current/ap...

Answer 3 links:
[json_util]: http://api.mongodb.org/python/current/ap...
[this question]: https://stackoverflow.com/questions/1987...

Answer 4 links:
[json.dumps]: https://docs.python.org/3/library/json.h...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #json #mongodb #flask

#avk47



ANSWER 1

Score 238


Bson in PyMongo distribution provides json_util - you can use that one instead to handle BSON types

from bson import json_util

def parse_json(data):
    return json.loads(json_util.dumps(data))



ACCEPTED ANSWER

Score 168


You should define you own JSONEncoder and using it:

import json
from bson import ObjectId

class JSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, ObjectId):
            return str(o)
        return json.JSONEncoder.default(self, o)

JSONEncoder().encode(analytics)

It's also possible to use it in the following way.

json.encode(analytics, cls=JSONEncoder)



ANSWER 3

Score 53


>>> from bson import Binary, Code
>>> from bson.json_util import dumps
>>> dumps([{'foo': [1, 2]},
...        {'bar': {'hello': 'world'}},
...        {'code': Code("function x() { return 1; }")},
...        {'bin': Binary("")}])
'[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]'

Actual example from json_util.

Unlike Flask's jsonify, "dumps" will return a string, so it cannot be used as a 1:1 replacement of Flask's jsonify.

But this question shows that we can serialize using json_util.dumps(), convert back to dict using json.loads() and finally call Flask's jsonify on it.

Example (derived from previous question's answer):

from bson import json_util, ObjectId
import json

#Lets create some dummy document to prove it will work
page = {'foo': ObjectId(), 'bar': [ObjectId(), ObjectId()]}

#Dump loaded BSON to valid JSON string and reload it as dict
page_sanitized = json.loads(json_util.dumps(page))
return page_sanitized

This solution will convert ObjectId and others (ie Binary, Code, etc) to a string equivalent such as "$oid."

JSON output would look like this:

{
  "_id": {
    "$oid": "abc123"
  }
}



ANSWER 4

Score 25


from bson import json_util
import json

@app.route('/')
def index():
    for _ in "collection_name".find():
        return json.dumps(i, indent=4, default=json_util.default)

This is the sample example for converting BSON into JSON object. You can try this.