Gerador de resposta paginada JSON
Gere uma resposta JSON paginada fictícia (com page, pageSize, total e items) para mockar uma API REST. Acelere o desenvolvimento e os testes de front-end.
—
JSON paginado mock: design de API do offset/limit ao cursor
Paginação é o problema ergonômico mais comum em design de APIs REST e GraphQL, e também um dos mais fáceis de errar. Um gerador de JSON paginado mock permite que times de front-end, devs mobile e autores de SDK construam telas, feeds com scroll infinito e tabelas antes do backend estar pronto, com envelopes de resposta que casam com o contrato de produção. Também serve como artefato didático: uma única ferramenta que emite variantes offset/limit, cursor, keyset e timestamp torna os trade-offs concretos e visíveis lado a lado.
Os quatro padrões canônicos são fáceis de reconhecer. Offset/limit usa ?page=2&limit=20 ou ?offset=20&limit=20; simples, permite pular para qualquer página, mas instável quando linhas são inseridas entre requisições e lento em tabelas grandes porque o banco ainda precisa contar e descartar as primeiras OFFSET linhas. Cursor-based usa um token opaco como ?cursor=eyJpZCI6MTAwfQ==; estável diante de inserções, rápido mesmo em bilhões de linhas, mas você não consegue saltar para a "página 50". Keyset (também chamado seek) expõe a chave de ordenação direto — ?after_id=100&limit=20 — e é o que a maioria dos cursores decodifica internamente. Timestamp-based, ?since=2024-01-01T00:00:00Z, é o ajuste natural para feeds de atividade e webhooks.
Envelopes de resposta e padrões de mercado
Uma resposta paginada quase sempre vem envolta em um envelope com duas partes: um array data com os itens e um objeto meta descrevendo a página. Campos comuns são current_page, per_page, total, total_pages, next_url e prev_url. A especificação JSON:API padroniza isso com um objeto links contendo URLs self, first, last, prev e next — um design HATEOAS em que o cliente segue links em vez de montá-los. GraphQL Relay usa connection + edges + pageInfo com endCursor e hasNextPage; Stripe retorna has_more e um auto_paging_iter() no SDK; GitHub coloca os dados de paginação no header HTTP Link em vez do corpo.
{
"data": [{ "id": 21, "name": "Item 21" }],
"meta": {
"current_page": 2,
"per_page": 20,
"total": 137,
"total_pages": 7
},
"links": {
"first": "/items?page=1&limit=20",
"prev": "/items?page=1&limit=20",
"next": "/items?page=3&limit=20",
"last": "/items?page=7&limit=20"
}
}
Paginação por cursor em detalhe
Cursores opacos costumam ser JSON em base64 contendo a chave de ordenação e o id do último item retornado, para o servidor disparar uma query WHERE (sort_key, id) > (last_sort, last_id) que atinge um índice. A opacidade importa: se os clientes aprenderem o formato, vão adulterá-lo, e mudar o schema depois quebra todo cursor cacheado por aí. Sempre inclua um byte de versão. Cursores são o default certo para feeds infinitos, logs de atividade, transações e qualquer endpoint apoiado em uma tabela que cresce continuamente; offset/limit serve para tabelas administrativas pequenas e resultados de busca em que "página 12" tem significado.
Tamanhos de página, limites e edge cases
Defaults sensatos: tamanho de página padrão 25, máximo 100, rejeite qualquer coisa maior com HTTP 400. Sempre documente o teto. Teste os edge cases que seu front vai bater: resultado vazio, resultado com exatamente limit itens (off-by-one na lógica de "tem próxima página?"), última página, requisição além da última página (retornar data vazia, não 404) e inserções concorrentes (cursor permanece estável, offset desloca). Um gerador mock que deixa você configurar total, per_page e current_page independentemente é a forma mais rápida de cobrir os quatro em testes de componente.
Perguntas frequentes
Cursor ou offset? Cursor para feeds infinitos, tabelas grandes, dados append-only e qualquer caso sensível a performance. Offset para listas administrativas pequenas, resultados de busca e qualquer cenário em que o usuário se beneficia de pular para uma página específica.
Que tamanho de página usar? Padrão 25, permita de 1 a 100, rejeite o resto. Cliente mobile costuma querer 20; exportações de dados querem 100.
Qual envelope é o padrão? Não existe um vencedor único. JSON:API é o mais prescritivo; o padrão estilo Stripe (data + has_more) é o mais copiado por APIs SaaS; o Link header do GitHub é o mais limpo mas o menos descobrível para quem consome via SDK.
Preciso retornar o total? Nem sempre. Devolver total exige uma segunda query (SELECT COUNT(*)) que pode dominar o tempo de resposta. Para feeds infinitos, has_more basta. Para tabelas paginadas que mostram "1-20 de 137", a contagem é inevitável.
Ferramentas Relacionadas
Gerador de AWS IAM Policy
Gera uma política IAM da AWS (versão 2012-10-17) a partir de Effect, Actions e Resources informados em texto.
Gerador de tabela de dados mock SQL
Gere comandos SQL (CREATE TABLE + INSERTs) com dados fictícios a partir do nome de uma tabela. Popule bancos de dados de teste e protótipos em segundos.
Gerador de JWT Aleatório (Fake)
Gera JWT com header/payload/signature aleatórios (sem assinatura válida) para mockar fluxos OAuth em desenvolvimento local.