0

I want to use Flask Restful to update a list with an object using a PUT request.

The resulting JSON should look like:

{"EmployeeID":"12345", "firstname":"Joe","lastname":"Bloggs","SupervisorName":"Name","SupervisorID":"2468","role":"Role","active":"True","hours":["{'date':'01/01/2017','qty':'3','project':'Project 1'}"]"}

The Hours field in the JSON is a list. The aim is to append an object to the list on each PUT request.

The Parser for hours is:

parser.add_argument('hours', action='append')

The Put method code is:

    def put(self, EmployeeID=None):
        data = parser.parse_args()
        if not data:
            data = {'ERROR': 'No Data'}
            return jsonify(data)
        else:
            if EmployeeID:
                if mongo.db.employee.find_one({'EmployeeID': EmployeeID}):
                    mongo.db.employee.update_one({'EmployeeID': EmployeeID}, {set: {"hours": data.get('hours')}})
                    return {'response': 'Employee:'+str(EmployeeID)+' updated'}
                else:
                    return {'Error': 'employee ' + str(EmployeeID) + ' not found'}

            else:
                return {'response': 'Employee ID missing'}

Is the update_one method the right one to use here?

using curl PUT request :

 curl -H "Content-type: application/json" -X PUT -d '{"EmployeeID":"1234",...,"hours":{'time':'','qty':'3','project':'Project 1'}}' http://127.0.0.1:5000/api/people/1234

Gave the error:

{
 "message": "Failed to decode JSON object: Expecting property name enclosed in double quotes: line 1 column 168 (char 167)"
}

But When I add the quotations into the request it return an error:

 {
 "message": "Failed to decode JSON object: Unterminated string starting at: line 1 column 167 (char 166)"
}

I can't figure out whether there is an issue with the requests or with the actual Flask-Restful code.

What is the correct way to go about updating a Mongo document list with an object?

Bchadwick
  • 347
  • 1
  • 5
  • 15

2 Answers2

-1

I don't have much experience with Flask, but from the error messages you've posted, it looks like the JSON in the request cannot be correctly decoded by Flask. I believe this is because you are using single quotes in your JSON string and are wrapping the entire JSON with yet another set of single quotes.

Try to just use double quotes in your JSON string and wrap the entire JSON string in single quotes like so:

curl -H "Content-type: application/json" -X PUT -d '{"EmployeeID":"1234","hours":{"time":"","qty":"3","project":"Project 1"}}' http://127.0.0.1:5000/api/people/1234

I think that should solve the issue of not being able to decode JSON form the request.

Karthic Raghupathi
  • 2,011
  • 5
  • 41
  • 57
  • That solved the JSON parsing issue thanks, Had to then change the update method to mongo.db.employee.update_one({'EmployeeID': EmployeeID}, {'$set': {"hours": data.get('hours')}}) – Bchadwick Feb 15 '17 at 16:14
  • Unfortunately this will overwrite the current object, I Then tried using the method '$addToSet', But this added a new list containg the object within the exisitng list – Bchadwick Feb 15 '17 at 16:19
  • I will add the answer once I find the correct solution here – Bchadwick Feb 15 '17 at 16:20
  • I believe you need to use the [$push](https://docs.mongodb.com/manual/reference/operator/update/push/) operator for this like so: `db.getCollection('employee').update({"EmployeeID" : ObjectId("58a480857cd7908d4fe69074")}, {"$push": { "hours": { "date" : "01/01/2017", "project" : "Project 2", "qty" : "4" }}});`. That is done in the MongoDb shell. You will need to adapt it to your python code. – Karthic Raghupathi Feb 15 '17 at 16:30
  • I ended up using the $addToSet method rather than $push. Not sure if there's much difference?? – Bchadwick Feb 15 '17 at 17:30
  • Per this [answer](http://stackoverflow.com/a/27248650/399435), `$addToSet` will not add the object to the array if it already contains the object. However, `$push` will add the object to the array anyway resulting in a duplicate. – Karthic Raghupathi Feb 15 '17 at 17:50
-1

If anyone runs into this issue I finally got there.

I had to change the RequestParser:

parser.add_argument('hours')

Removing the action='append'

Then using the mongo update:

mongo.db.employee.update_one({'EmployeeID': EmployeeID}, {'$addToSet': {"hours": data.get('hours')}}) 
Bchadwick
  • 347
  • 1
  • 5
  • 15