Skip to content

Commit 1091d89

Browse files
committed
minor #17301 [HttpFoundation] Add documentation for StreamedJsonResponse (alexander-schranz)
This PR was squashed before being merged into the 6.3 branch. Discussion ---------- [HttpFoundation] Add documentation for `StreamedJsonResponse` Docs for: symfony/symfony#47709 # TODO - [x] Example of Flush Handling Commits ------- 8a285e3 [HttpFoundation] Add documentation for `StreamedJsonResponse`
2 parents a5cd2f6 + 8a285e3 commit 1091d89

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

components/http_foundation.rst

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,103 @@ represented by a PHP callable instead of a string::
631631

632632
.. _component-http-foundation-serving-files:
633633

634+
Streaming a JSON Response
635+
~~~~~~~~~~~~~~~~~~~~~~~~~
636+
637+
.. versionadded:: 6.3
638+
639+
The :class:`Symfony\\Component\\HttpFoundation\\StreamedJsonResponse` class was
640+
introduced in Symfony 6.3.
641+
642+
The :class:`Symfony\\Component\\HttpFoundation\\StreamedJsonResponse` allows an API to
643+
return a lot of data as JSON and keep the used resources low by make usage of Generators.
644+
645+
It expects an array which represents the JSON structure and the list which should be
646+
streamed are represented in the array as ``\Generator``. It also supports any kind of
647+
Traversable containing JSON serializable data for a good developer experience,
648+
but for keep the resources usage as low as possible, it is recommended to use ``\Generators``,
649+
as they the advantages that only the current returned data need to be keep in memory.
650+
651+
The response will stream the JSON with generators in to most efficient way and keep resources as low as possible::
652+
653+
use Symfony\Component\HttpFoundation\StreamedJsonResponse;
654+
655+
function loadArticles(): \Generator { // any method or function returning a Generator
656+
yield ['title' => 'Article 1'];
657+
yield ['title' => 'Article 2'];
658+
yield ['title' => 'Article 3'];
659+
};
660+
661+
$response = new StreamedJsonResponse(
662+
// json structure with generators in which will be streamed as a list
663+
[
664+
'_embedded' => [
665+
'articles' => loadArticles(), // any \Generator can be used which will be streamed as list of data
666+
],
667+
],
668+
);
669+
670+
.. tip::
671+
672+
If loading data via doctrine the ``toIterable`` method of ``Doctrine`` can be
673+
used to keep the resources low and fetch only row by row.
674+
See the `Doctrine Batch processing`_ documentation for more::
675+
676+
public function __invoke(): Response
677+
{
678+
return new StreamedJsonResponse(
679+
[
680+
'_embedded' => [
681+
'articles' => $this->loadArticles(),
682+
],
683+
],
684+
);
685+
}
686+
687+
public function loadArticles(): \Generator
688+
{
689+
$queryBuilder = $entityManager->createQueryBuilder();
690+
$queryBuilder->from(Article::class, 'article');
691+
$queryBuilder->select('article.id')
692+
->addSelect('article.title')
693+
->addSelect('article.description');
694+
695+
return $queryBuilder->getQuery()->toIterable();
696+
}
697+
698+
.. tip::
699+
700+
If you have a lot of data to be returned you may want to call the
701+
PHP `flush <https://www.php.net/manual/en/function.flush.php>`__ method between
702+
to flush the response after every specific count of items::
703+
704+
public function __invoke(): Response
705+
{
706+
return new StreamedJsonResponse([
707+
'_embedded' => [
708+
'articles' => $this->loadArticles(),
709+
],
710+
]);
711+
}
712+
713+
public function loadArticles(): \Generator
714+
{
715+
$queryBuilder = $entityManager->createQueryBuilder();
716+
$queryBuilder->from(Article::class, 'article');
717+
$queryBuilder->select('article.id')
718+
->addSelect('article.title')
719+
->addSelect('article.description');
720+
721+
$count = 0;
722+
foreach ($queryBuilder->getQuery()->toIterable() as $article) {
723+
yield $article;
724+
725+
if (++$count % 100 === 0) {
726+
flush();
727+
}
728+
}
729+
}
730+
634731
Serving Files
635732
~~~~~~~~~~~~~
636733

@@ -866,3 +963,4 @@ Learn More
866963
.. _`JSON Hijacking`: https://haacked.com/archive/2009/06/25/json-hijacking.aspx/
867964
.. _OWASP guidelines: https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html#always-return-json-with-an-object-on-the-outside
868965
.. _RFC 8674: https://tools.ietf.org/html/rfc8674
966+
.. _Doctrine Batch processing: https://www.doctrine-project.org/projects/doctrine-orm/en/2.14/reference/batch-processing.html#iterating-results

0 commit comments

Comments
 (0)