0

Although I am returning a sorted dictionary by value, FastAPI response is not sorted.

I'm using

  • python: 3.8.10
  • fastapi: 0.95.2
This is my endpoint:
@classifier_router.post("/groupClassifier")
async def group_classifier(
    # current_user: User = Depends(get_current_user),
    group_id: str = Query(default="1069302375", description=GROUP_ID_DESC),
    starttime: Union[datetime , None] = DEFAULT_START_TIME,
    endtime: Union[datetime , None] = DEFAULT_END_TIME):
    result = handler.group_classifier(
        [group_id],
        starttime,
        endtime)
    if result==None:
        raise HTTPException(
        status_code=500
        )
    else:
        return result
Result which returned in swagger:
{
  "class_scores": {
    "1": 34.8,
    "2": 22.1,
    "3": 16.9,
    "4": 7.8,
    "5": 26,
    "6": 23.6
  }
}
RF1991
  • 2,037
  • 4
  • 8
  • 17
Mostafa Najmi
  • 315
  • 1
  • 4
  • 11

1 Answers1

0

To answer the question first, In FastAPI when you return a dict in your endpoint, it will use it's internal json encode to serialize your output, in this case it probably uses something like: json.dumps(..., sort_keys=True) by default. To avoid that you can return a JsonResponse directly:

from fastapi.responses import JSONResponse

@classifier_router.post("/groupClassifier")
async def group_classifier(
    # current_user: User = Depends(get_current_user),
    group_id: str = Query(default="1069302375", description=GROUP_ID_DESC),
    starttime: Union[datetime , None] = DEFAULT_START_TIME,
    endtime: Union[datetime , None] = DEFAULT_END_TIME):
    result = handler.group_classifier(
        [group_id],
        starttime,
        endtime)
    if result is None:
        raise HTTPException(status_code=500)
    return JSONResponse(content=result)

on other note, if order is important for you, maybe using a dict is not the most appropriate data structure, you should probably look into returning a list of dicts, or simply a list with the index of the class score being the equivalent of the key

obendidi
  • 63
  • 2
  • 7
  • Thanks. Now output is sorted but output is not in json format: `"{\"class_scores\": {\"1\": 34.4, \"5\": 26.0, \"6\": 23.4, \"2\": 22.1, \"3\": 16.9, \"4\": 7.8}}"` – Mostafa Najmi Jul 29 '23 at 09:56
  • my bad, `JsonResponse` takes a dict as input. Looking at the source code it doesn't seem to run `sort_keys` on the dict so it should be safe: https://github.com/encode/starlette/blob/master/starlette/responses.py#L167 – obendidi Jul 29 '23 at 10:01
  • I changed return. But output is not sorted yet. – Mostafa Najmi Jul 29 '23 at 10:11
  • As @obendidi wrote, if you want the response sorted, don't use a dictionary. Even if your JSON is sorted, there is no guarantee it remains sorted in the receiving client. If order is important, use an array, something like `{"class_scores": [{"score": 1, "percentage": 34.8}, {"score": 2, "percentage": 22.1}, ...]}` – M.O. Jul 29 '23 at 10:36