관리 메뉴

솜씨좋은장씨

[MongoDB x Flask] TypeError: Object of type Cursor is not JSON serializable 해결방법 본문

Programming/NoSQL

[MongoDB x Flask] TypeError: Object of type Cursor is not JSON serializable 해결방법

솜씨좋은장씨 2020. 5. 1. 17:37
728x90
반응형

 

 

[Python] flask와 mongoDB를 활용하여 REST API 만들기 1 - CSV 데이터를 불러와 mongoDB에 데이터 추가하기

1. 필요한 라이브러리 설치하기 pip install pymongo pip install pandas pip install tqdm 먼저 필요한 라이브러리를 설치합니다. 2. csv에서 데이터 불러와서 json 형태로 만들기 CSV는 지난 캐치 프로그램 과..

somjang.tistory.com

지난번에 크롤링을 통해서 데이터를 저장해 놓은 mongoDB와 Flask를 활용하여 API를 만들어보면서

pymongo를 통해 mongoDB에서 가져온 데이터를 flask의 jsonify를 거쳐 return 하려고 하면 

 

Code

from flask import Flask, jsonify
from pymongo import MongoClient

app = Flask(__name__)

my_client = MongoClient("mongodb://localhost:27017/")

@app.route('/movie_api')
def hello():
    my_db = my_client['movie_flask_api_db']
    mycol = my_db['movie_data']
    my_doc = mycol.find().sort("advanceRate", -1)

    movie = str(my_doc[0])
    
    return jsonify(movie)
    
if __name__ == '__main__':
    app.run(host='0.0.0.0', debug='True')  

Error Message

TypeError: Object of type Cursor is not JSON serializable 

계속 위와 같은 오류를 만나게 되었습니다.

 

오늘은 검색을 통해서 찾아 해결한 방법을 기록해두려합니다.

 

해결 방법

먼저 mongoengine이라는 라이브러리를 설치하였습니다.

$ pip3 install mongoengine

그 다음 mongoengine_jsonencoder.py 라는 파일을 하나 만들고

from flask import Flask
from flask.json import JSONEncoder
from bson import json_util
from mongoengine.base import BaseDocument
from mongoengine.queryset.base import BaseQuerySet

class MongoEngineJSONEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, BaseDocument):
            return json_util._json_convert(obj.to_mongo())
        elif isinstance(obj, BaseQuerySet):
            return json_util._json_convert(obj.as_pymongo())
        return JSONEncoder.default(self, obj)

위처럼 코드를 작성하고 저장하였습니다.

 

그런 다음 아까 오류가 났던 코드로 돌아와서

from flask import Flask, jsonify
from pymongo import MongoClient
from bson import json_util
from mongoengine_jsonencoder import MongoEngineJSONEncoder

app = Flask(__name__)
app.json_encoder = MongoEngineJSONEncoder

my_client = MongoClient("mongodb://localhost:27017/")

@app.route('/movie_api')
def hello():
    my_db = my_client['movie_flask_api_db']
    mycol = my_db['movie_data']
    my_doc = mycol.find().sort("advanceRate", -1)

    movie = ''

    isFirst = True
    for doc in my_doc:
        if isFirst == True:
            movie = movie + str(doc)
            isFirst = False
        else:
            movie = movie + ', ' + str(doc)

    return jsonify(movie)

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug='True')

코드를 변경하였습니다.

 

어떤 점을 변경하였는지 자세하게 살펴보면 다음과 같습니다.

from bson import json_util
from mongoengine_jsonencoder import MongoEngineJSONEncoder

아까 만들어두었던 mongoengine_jsonencoder를 import 해주고 bson도 import 해줍니다.

app.json_encoder = MongoEngineJSONEncoder

그 다음 위의 코드를 추가합니다.

 

그럼 설정 끝!

 

그 뒤의 코드들은 제가 데이터를 하나만 출력하다가 여러 개를 한번에 보고 싶어서 수정한 코드입니다.

 

이렇게 설정해주고 postman을 통해 제대로 결과가 출력되는지 확인해보면!

http://localhost:5000/movie_api

오류없이 제대로 데이터를 받아볼 수 있는 것을 확인할 수 있습니다.

 

좀 더 공부해서 CRUD기능을 가진 API를 제대로 만들어보려합니다.

 

읽어주셔서 감사합니다!

Comments