diff --git a/fastapi/routing.py b/fastapi/routing.py index f383f995c..c3e3e9899 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -516,7 +516,17 @@ def get_request_handler( exclude_none=response_model_exclude_none, ) else: - data_str = json.dumps(jsonable_encoder(item.data)) + data_str = json.dumps( + jsonable_encoder( + item.data, + include=response_model_include, + exclude=response_model_exclude, + by_alias=response_model_by_alias, + exclude_unset=response_model_exclude_unset, + exclude_defaults=response_model_exclude_defaults, + exclude_none=response_model_exclude_none, + ) + ) else: data_str = None return format_sse_event( diff --git a/tests/test_sse.py b/tests/test_sse.py index 3b8bd1126..3efd43e4f 100644 --- a/tests/test_sse.py +++ b/tests/test_sse.py @@ -132,6 +132,24 @@ async def sse_items_event_model_data_exclude_defaults(): yield ServerSentEvent(data=AliasedItemWithDefaults(name="Portal Gun")) +@app.get( + "/items/stream-sse-event-dict-data-include", + response_class=EventSourceResponse, + response_model_include={"name"}, +) +async def sse_items_event_dict_data_include(): + yield ServerSentEvent(data={"name": "Portal Gun", "hidden": "secret"}) + + +@app.get( + "/items/stream-sse-event-list-model-data-no-alias", + response_class=EventSourceResponse, + response_model_by_alias=False, +) +async def sse_items_event_list_model_data_no_alias(): + yield ServerSentEvent(data=[AliasedItem(name="Portal Gun")]) + + @app.get("/items/stream-mixed", response_class=EventSourceResponse) async def sse_items_mixed() -> AsyncIterable[Item]: yield items[0] @@ -318,6 +336,27 @@ def test_sse_event_model_data_respects_response_model_serialization_options( assert response.text == f"data: {expected_data}\n\n" +@pytest.mark.parametrize( + ("path", "expected_data"), + [ + ( + "/items/stream-sse-event-dict-data-include", + '{"name": "Portal Gun"}', + ), + ( + "/items/stream-sse-event-list-model-data-no-alias", + '[{"name": "Portal Gun"}]', + ), + ], +) +def test_sse_event_jsonable_encoder_data_respects_response_model_serialization_options( + client: TestClient, path: str, expected_data: str +): + response = client.get(path) + assert response.status_code == 200 + assert response.text == f"data: {expected_data}\n\n" + + def test_mixed_plain_and_sse_events(client: TestClient): response = client.get("/items/stream-mixed") assert response.status_code == 200