2

I get the following error when I try to access the 'data' variable from the endpoint '/'.

ValueError: [ValueError('dictionary update sequence element #0 has length 1; 2 is required'), TypeError('vars() argument must have __dict__ attribute')]

This is how FastAPI backend looks like:

from fastapi import FastAPI
app = FastAPI()
data = {}
@app.on_event("startup")
def startup_event():
    data[1]  =  [...] ...(numpy array)
    data[2]  = [...] ...(numpy array)
    return data


@app.get("/")
def home():
    return {'Data': data}

When I launch the endpoint I see 'Internal Server Error'. Nothing would display at the endpoint '/'. However, if I add this line -> 'print(data)' just above the return in home function for endpoint '/', it does print the values stored in the data dictionary, as specified in the startup function. How can I fix the issue, so that the data variable becomes visible when accessing the '/' endpoint?

Chris
  • 18,724
  • 6
  • 46
  • 80
catBuddy
  • 367
  • 1
  • 3
  • 15
  • where is data defined and what does it look like? – Sandil Ranasinghe Feb 25 '22 at 09:14
  • I added three more lines of code to the above code snippet. Here, app = FastAPI() data = {} ... startup: ... function definition – catBuddy Feb 25 '22 at 09:18
  • 1
    I just copy pasted your code and it seems to run fine for me, maybe there is some other part in your code that causes the problem? – Sandil Ranasinghe Feb 25 '22 at 09:23
  • Really? Could you see the results when you visit endpoint '/'? There is only import statements apart from the code I wrote. – catBuddy Feb 25 '22 at 09:34
  • 1
    Yeah. I get this `{"Data":{"1":1,"2":11}}` at the endpoint '/' . Do you have any more information in your error log? – Sandil Ranasinghe Feb 25 '22 at 09:40
  • Yes, I figured. When I change the values to be numpy arrays then, they do not work. I get internal server error. – catBuddy Feb 25 '22 at 11:00
  • FastAPI has no idea how it should decode numpy arrays as JSON. Return a native Python datatype or JSON yourself. Also, include the actual error message you get in your question as that makes it easier for other people to debug your problem. – MatsLindh Feb 25 '22 at 11:03
  • Solved. Had to convert numpy array to json – catBuddy Feb 25 '22 at 11:10

2 Answers2

1

Option 1

You should convert (serialise) any numpy arrays into JSON before returning the data. Example:

data = {}
data[1] = json.dumps(np.array([1, 2, 3, 4]).tolist())
data[2] = json.dumps(np.array([5, 6, 7, 8]).tolist())
return data

Option 2

Alternatively, you could serialise the whole dictionary object and return it in a custom Response, such as below:

from fastapi import Response

json_data = json.dumps({k: v.tolist() for k, v in data.items()})
return Response(content=json_data, media_type="application/json")

Option 3

Another option would be to use jsonable_encoder—which is used internally by FastAPI when returning a value, in order to convert objects that are not serializable into str—and then, return a JSONResponse, or a custom Response directly (as demonstrated in the previous option), which will return an application/json encoded response to the client, as described here.

from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder

json_data = jsonable_encoder({k: v.tolist() for k, v in data.items()})
return JSONResponse(content=json_data)
Chris
  • 18,724
  • 6
  • 46
  • 80
0

FastAPI has no idea how it should decode numpy arrays to JSON; instead, do it explicitly yourself and then return the structure as native Python datatypes or as a raw JSON string. You can do this by using the custom Response objects in FastAPI.

return Response(content=numpy_as_json, media_type="application/json")

Or if you have it formatted as native datatypes:

return JSONResponse(content=numpy_as_native_datatypes)
MatsLindh
  • 49,529
  • 4
  • 53
  • 84