A nova API do Dados Abertos entrega dados em XML e JSON de forma paginada. Neste tutorial, você pode saber mais sobre como funciona o mecanismo de paginação, e ver um exemplo em HTML e JavaScript com uma forma de juntar os resultados de diferentes requisições em um só conjunto de dados.

A nova interface de programação de aplicações (API) do serviço Dados Abertos da Câmara foi projetada para fazer jus ao nome: sua finalidade principal é fornecer conjuntos reduzidos de dados, selecionados por meio de diversos parâmetros de busca, para aplicações leves que exibam ou processem esses dados de maneiras particulares. É um tipo de trabalho diferente do que é feito com os arquivos de dados para download, que contêm todas as informações sobre todos os itens de suas respectivas entidades — e por isso exigem disponibilidade de comunicação ("largura de banda") para o download de vários megabytes de uma vez, grandes espaços de memória RAM e processamento intenso na seleção e cruzamento dos dados.
Para manter os conjuntos de dados selecionados relativamente pequenos e a transferência deles mais veloz, a nova API segue um padrão muito comum em outras interfaces que seguem a arquitetura REST: as URLs (ou, mais corretamente, os recursos) que fornecem resultados em listas dividem o resultado em páginas.
Todas as respostas válidas do novo Dados Abertos, tanto em JSON quanto em XML, são entregues em uma estrutura padronizada de organização. Há uma seção com o nome dados, contendo os resultados
da requisição, e uma seção com o nome links. O conteúdo de dados, nos recursos coletivos, é uma lista ordenada de itens que correspondam aos parâmetros de busca utilizados.
<xml>
<dados>
<partido_>
...
</partido_>
<partido_>
...
</partido_>
...
</dados>
<links>
<link>
<rel>self</rel>
<href>"..."</href>
</link>
<link>
<rel>next</rel>
<href>"..."</href>
</link>
<link>
<rel>previous</rel>
<href>"..."</href>
</link>
<link>
<rel>first</rel>
<href>"..."</href>
</link>
<link>
<rel>last</rel>
<href>"..."</href>
</link>
</links>
</xml>
{
"dados": [
{
...
},
{
...
},
...
],
"links": [
{
"rel": "self",
"href": "http://...",
},
{
"rel": "previous",
"href": "http://...",
},
{
"rel": "next",
"href": "http://...",
},
{
"rel": "first",
"href": "http://...",
},
{
"rel": "last",
"href": "http://...",
}
]
}
Cada elemento link tem dois campos: href traz uma URL e rel é um termo que descreve a relação que a URL tem com o documento ou recurso retornado. Esses termos usados com rel são de certa forma padronizados, e por serem divulgados no site da Internet Assigned Numbers Authority (IANA) são conhecidos popularmente
como "relações IANA".
Nem sempre todos os links mostrados nos exemplos estão presentes, e não precisam aparecer no resultado nesta mesma ordem. O valor do campo rel indica os seguintes significados para as URLs:
O uso dos links, e principalmente de suas descrições semânticas dos campos rel, são recomendações fundamentais da arquitetura REST e da chamada "Web 3.0". É que está na essência de conceitos como linked data e HATEOAS (Hypermedia As The Engine Of Application State, ou "hipermídia como o motor de estado da aplicação").
Na API do Dados Abertos, todos os recursos coletivos (isto é, que fornecem listagens) que têm suporte a paginação usam os mesmos parâmetros de query string para configurá-la:
Para se obter, por exemplo, uma lista de dados de 50 deputados de cada vez, a URL inicial seria .../deputados?itens=50. Na resposta dessa primeira requisição, haveria um link, identificado com o parâmetro rel com o valor next, com a URL já configurada como .../deputados?itens=50&pagina=2, para a obtenção dos dados dos 50 deputados seguintes.
O correto uso dos elementos link permite que você obtenha todos os itens de um recurso paginado, de qualquer tamanho total, usando um conceito simples: enquanto cada resposta tiver um link cujo campo rel tenha o valor next, é só fazer uma nova requisição usando a URL que esse link traz como valor do campo href.
É fácil imaginar isso como um loop, mas em linguagens como JavaScript as requisições para obter dados via rede são feitas de maneira assíncrona: logo que a requisição é feita, o fluxo do programa continua
sem esperar a resposta, e é preciso definir o que vai acontecer quando enfim essa resposta chegar. Essa característica exige uma abordagem um pouco diferente daquela de loop WHILE que se poderia imaginar
para o problema.
Neste tutorial, é criada uma simples página HTML, sem qualquer formatação visual, que monta uma lista com todos os deputados em exercício, usando a API do Dados Abertos, e exibe os nomes desses deputados em um menu tipo combobox. Ao escolher qualquer dos nomes, é exibida na página a foto do parlamentar.
A abordagem dessa aplicação para montar uma só lista com várias requisições (que não pretende ser apresentada como a melhor, é importante observar) é centrada na variável global listaDeps. É definida
uma função a ser executada quando chegar a resposta, e a cada vez que é chamada essa função acrescenta os dados retornados à lista. No jargão técnico, esse tipo de função, que é invocada como reação de resposta a um evento,
é chamada de callback.
Além de acrescentar itens a listaDeps, a função verifica a existência de um link cujo rel seja next na resposta à requisição. Isso é feito em um loop FOR que
verifica o conteúdo do campo rel em todos os nós ou objetos link que são retornados como itens da lista links. Há também, comentada, uma versão que usa o método .forEach() da variável.
Assim que é encontrado um link de rel igual a next, a URL que está nesse link, em seu campo href, é usada como argumento para chamar a função principal que cria uma nova requisição,
buscarListaDeps. A cada vez que é invocada, buscarListaDeps cria uma nova callback para a chegada da resposta — e todo o processo se repete até que não haja mais links next a obter.
<doctype html>
<html lang="pt-br">
<head>
<title>Quem é quem dos deputados</title>
<meta charset="UTF-8"/>
<script>
"use strict";
var listaDeps = new Array();
/* buscarListaDeps
Carrega 'listaDeps' com os dados obtidos do recurso paginado,
em chamadas sucessivas
*/
function buscarListaDeps (urlInicio) {
var corpoResposta;
var req = new XMLHttpRequest();
var dados;
req.open ("GET", urlInicio);
req.onreadystatechange = function (evt) {
if (req.readyState === req.DONE &&
req.status >= 200 && req.status < 300) {
// A requisição foi respondida com sucesso.
corpoResposta = JSON.parse(req.responseText);
listaDeps = listaDeps.concat(corpoResposta.dados);
// Se houver um link de rel="next" na resposta, chamar a função de busca
// outra vez usando esse link
// VERSÃO COM LOOP FOR
for (var i = 0; i < corpoResposta.links.length; i++) {
if (corpoResposta.links[i].rel === "next") {
buscarListaDeps(corpoResposta.links[i].href);
return;
}
}
/* VERSÃO USANDO FOREACH
corpoResposta.links.forEach (
function (val, idx, arr) {
if (val.rel === "next") {
buscarListaDeps (val.href);
return;
}
}
);
*/
menuCarregarOpcoes();
} // FIM DO "IF"
} // FIM DE onreadystatechange
req.setRequestHeader ("Accept", "application/json");
req.send();
}
buscarListaDeps("https://dadosabertos.camara.leg.br/api/v2/deputados?itens=100");
/* menuCarregarOpcoes
Configura as opções de nomes de deputados no menu
*/
function menuCarregarOpcoes() {
var i=0;
var menuwdg = document.getElementById("menudeps");
var opt;
// Criar o primeiro item sem o nome de um parlamentar...
opt = document.createElement("option");
opt.text = "Escolha um parlamentar..."
menuwdg.add(opt);
while (listaDeps[i]) {
opt = document.createElement("option");
opt.text = listaDeps[i].nome;
menuwdg.add(opt);
i++;
}
}
/* menuOpcaoEscolhida
Chamada quando o usuário escolhe outro nome no menu, executa
as alterações na foto e no quadro de informações.
*/
function menuOpcaoEscolhida() {
var escolhido;
var menuwdg = document.getElementById("menudeps");
escolhido = menuwdg.value;
for (var i = 0; i < listaDeps.length; i++) {
if (listaDeps[i].nome === escolhido) {
mostrarDeputado (listaDeps[i]);
}
}
}
/*
mostrarDeputado - recebe um item da lista de deputados,
contendo os dados de um parlamentar, e os insere na
exibição do HTML no navegador
*/
function mostrarDeputado (dep) {
var wdgFoto = document.getElementById("fotodep");
var wdgNome = document.getElementById("nomedep");
var wdgPartEst = document.getElementById("part-est");
// A URL da foto é colocada como valor do atributo "src"
// do elemento <img> identificado com o id "fotodep"
wdgFoto.setAttribute("src", dep.urlFoto);
// O nome é inserido como conteúdo do elemento com id "nome"
wdgNome.innerHTML = dep.nome;
wdgPartEst.innerHTML = dep.siglaPartido + "-" + dep.siglaUf;
}
</script>
</head>
<body>
<!-- Aqui é criado o controle de menu -->
<select id="menudeps" onchange="menuOpcaoEscolhida()"></select><br/>
<!-- A foto é exibida neste elemento "img"... -->
<br/>
<img id="fotodep" src="../../img/howtouse/avatar-anonimo.png" width="200"/>
<br/>
<!-- Nome e estado -->
<h3 id="nomedep"></h3>
<h4 id="part-est"></h4>
</body>
</html>