Este é o primeiro tutorial de dois sobre JSON no R. Nesta primeira parte, mostro como usar o pacote jsonlite
para converter de JSON para R e vice-versa. Na segunda parte, trato de como trabalhar com JSON como JSON mesmo no R, sem convertê-lo para lista ou dataframe.
Um dos formatos de arquivos que eu mais gosto de trabalhar é JSON (JavaScript Object Notation). A graça de JSON é ser um formato amigável para seres humanos e para máquinas. Coloco abaixo o exemplo de parte de um currículo.
{"id": 2,
"data": "2022-01-01",
"nome": {
"primeiro_nome": "José",
"sobrenome": "de Jesus Filho"
},"cpf": "123.456.789-34",
"disponivel": true,
"educacao": [
{"escola": "EMPG Milton Campos",
"ensino": "Fundamental",
"inicio": 1982,
"fim": 1989
},
{"escola": "Derville Allegretti",
"ensino": "medio",
"inicio": 1990,
"fim": 1992
}
],"experiencia_profissional": [
{"empresa": "Companhia Brasileria de Distribuição",
"cargo": "empacotador",
"inicio": 1986,
"fim": 1988
},
{"empresa": "Compneus",
"cargo": "gerente",
"inicio": 1990,
"fim": 1992
},
{"empresa": "Varias",
"cargo": "muitos",
"inicio": 1992,
"fim": 2021
},
{"empresa": "MPSP",
"cargo": "Jurimetrista",
"inicio": 2022,
"fim": null
}
] }
Diferentemente de XML, JSON é simples e fácil de manipular. No entanto, essa simplicidade vem com um custo. JSON carece de namespace, o que facilmente pode gerar conflitos e perda de integridade dos dados. Se você quer entender para que serve namespace, carregue o pacote dplyr e busque a ajuda para a função filter
, você notará que há duas funções distintas com o mesmo nome, porém uma no namespace dplyr e outra no stats. Pacotes são namespaces, schemas em SQL são namespaces e XML também usa namespaces. Namespaces asseguram unicidade nos nomes dos objetos.
Ademais, JSON só reconhece quatro (4) tipos/classes de dados (texto, número, boleano e nulo). Datas e dados categóricos (fatores ou enum) não são reconhecidos. Além disso, JSON têm duas estruturas universais:
JSON objeto: Uma coleção desordenada de pares chave/valor. Esses valores podem ser aqueles acima mencionados: texto (string), número (number), boleano (boolean) e nulo, bem como os próprios objetos JSON e arrays.
JSON array: Uma coleção ordenada de valores.
Note acima que o JSON está dentro de chaves {…}, indicando que se trata de um objeto JSON. Nele há vários objetos: id, data, nome, cpf, disponivel, educacao e experiencia_profissional. O id é numérico, data, nome e cpf são textos e disponível é lógico (boleano). Por sua vez, educacao e experiencia_profissional são arrays. Arrays estão sempre entre colchetes.
Perceba também que as chaves ou nomes (keys) estão sempre entre aspas e os valores, quando textos também entre aspas, números, boleanos e nulos (último ítem “fim” da experiência profissional), sem aspas.
O exemplo acima é simples e fácil de entender, mas JSON pode ser complexo, com profundos aninhamentos de objetos e arrays, o que torna a conversão de um JSON para um objeto nativo do R e vice-versa um desafio e sujeita a erros de toda sorte.
Neste tutorial, mostraremos como trabalhar como pacote jsonlite, o qual converte JSON em objetos do R e vice-versa. No próximo, falaremos do pacote jqr, o qual manuseia JSON como JSON mesmo, sem convertê-lo para lista ou data.frame.
O pacote jsonlite permite ler, escrever e validar JSONs. Vamos tratar do exemplo acima:
x <- '{
"id": 2,
"data": "2022-01-01",
"nome": {
"primeiro_nome": "José",
"sobrenome": "de Jesus Filho"
},
"cpf": "123.456.789-34",
"disponivel": true,
"educacao": [
{
"escola": "EMPG Milton Campos",
"ensino": "Fundamental",
"inicio": 1982,
"fim": 1989
},
{
"escola": "Derville Allegretti",
"ensino": "medio",
"inicio": 1990,
"fim": 1992
}
],
"experiencia_profissional": [
{
"empresa": "Companhia Brasileria de Distribuição",
"cargo": "empacotador",
"inicio": 1986,
"fim": 1988
},
{
"empresa": "Compneus",
"cargo": "gerente",
"inicio": 1990,
"fim": 1992
},
{
"empresa": "Varias",
"cargo": "muitos",
"inicio": 1992,
"fim": 2021
},
{
"empresa": "MPSP",
"cargo": "Jurimetrista",
"inicio": 2022,
"fim": null
}
]
}'
o pacote jsonlite
possui um função para converter JSON para objeto do R chamada fromJSON
:
$id
[1] 2
$data
[1] "2022-01-01"
$nome
$nome$primeiro_nome
[1] "José"
$nome$sobrenome
[1] "de Jesus Filho"
$cpf
[1] "123.456.789-34"
$disponivel
[1] TRUE
$educacao
escola ensino inicio fim
1 EMPG Milton Campos Fundamental 1982 1989
2 Derville Allegretti medio 1990 1992
$experiencia_profissional
empresa cargo inicio fim
1 Companhia Brasileria de Distribuição empacotador 1986 1988
2 Compneus gerente 1990 1992
3 Varias muitos 1992 2021
4 MPSP Jurimetrista 2022 NA
A vantagem do jsonlite
é que ele opera um excelente mapeamento entre JSON e objetos do R. O JSON foi convertido numa lista de sete elementos, dos quais alguns vetores de um único elemento, nome é uma lista, e educacao e experiencia_profissional são dataframes. Além disso, os textos foram convertidos para characters, números tornaram-se integers, true foi propriamente convertido para TRUE e null para NA.
A data foi mantida como character porque JSON não tem especificação para datas.
O pacote jsonlite
possibilita o caminho reverso por meio da função toJSON
:
toJSON(obj)
{“id”:[2],“data”:[“2022-01-01”],“nome”:{“primeiro_nome”:[“José”],“sobrenome”:[“de Jesus Filho”]},“cpf”:[“123.456.789-34”],“disponivel”:[true],“educacao”:[{“escola”:“EMPG Milton Campos”,“ensino”:“Fundamental”,“inicio”:1982,“fim”:1989},{“escola”:“Derville Allegretti”,“ensino”:“medio”,“inicio”:1990,“fim”:1992}],“experiencia_profissional”:[{“empresa”:“Companhia Brasileria de Distribuição”,“cargo”:“empacotador”,“inicio”:1986,“fim”:1988},{“empresa”:“Compneus”,“cargo”:“gerente”,“inicio”:1990,“fim”:1992},{“empresa”:“Varias”,“cargo”:“muitos”,“inicio”:1992,“fim”:2021},{“empresa”:“MPSP”,“cargo”:“Jurimetrista”,“inicio”:2022}]}
A primeira observação é que JSON não está nada elegante nem formatado para facilitar a leitura humana. Igualmente, percebe-se que os vetores de um único elemento foram todos convertidos em arrays. Por fim, a chave-valor fim do último cargo, que era NA no R simplesmente desapareceu.
A função toJSON
possui argumentos para reverter isso.
toJSON(obj,
pretty = T, ## Tornar amigável ao usuário
na = "null", ## converte NA para nulo
auto_unbox = TRUE) ## retira os colchetes dos elementos únicos.
{
"id": 2,
"data": "2022-01-01",
"nome": {
"primeiro_nome": "José",
"sobrenome": "de Jesus Filho"
},
"cpf": "123.456.789-34",
"disponivel": true,
"educacao": [
{
"escola": "EMPG Milton Campos",
"ensino": "Fundamental",
"inicio": 1982,
"fim": 1989
},
{
"escola": "Derville Allegretti",
"ensino": "medio",
"inicio": 1990,
"fim": 1992
}
],
"experiencia_profissional": [
{
"empresa": "Companhia Brasileria de Distribuição",
"cargo": "empacotador",
"inicio": 1986,
"fim": 1988
},
{
"empresa": "Compneus",
"cargo": "gerente",
"inicio": 1990,
"fim": 1992
},
{
"empresa": "Varias",
"cargo": "muitos",
"inicio": 1992,
"fim": 2021
},
{
"empresa": "MPSP",
"cargo": "Jurimetrista",
"inicio": 2022,
"fim": null
}
]
}
Se você quiser salvar um objeto do R como JSON, use a função write_JSON
com os mesmos argumentos da toJSON
adicionados do argumento path
:
write_JSON(obj,
path = "curriculo.JSON",
pretty = TRUE,
na = "JSON",
auto_unbox = TRUE)
Por vezes, você quer converter um objeto R para JSON e revertê-lo posteriormente para R. A título de exemplo, vamos criar simples tibble e convertê-la para JSON.
[
{
"a": 1,
"b": "a"
},
{
"a": 2,
"b": "b"
},
{
"a": 3,
"b": "c"
},
{
"a": 4,
"b": "d"
},
{
"a": 5,
"b": "e"
}
]
Se quisermos nossa tibble de volta, o resultado pode ser frustrante:
O pacote jsonlite
oferece duas alternativas a toJSON
e fromJSON
, as quais preservam os atributos originais:
sJSON <- serializeJSON(df, pretty = T)
sJSON
{
"type": "list",
"attributes": {
"class": {
"type": "character",
"attributes": {},
"value": ["tbl_df", "tbl", "data.frame"]
},
"row.names": {
"type": "integer",
"attributes": {},
"value": [1, 2, 3, 4, 5]
},
"names": {
"type": "character",
"attributes": {},
"value": ["a", "b"]
}
},
"value": [
{
"type": "integer",
"attributes": {},
"value": [1, 2, 3, 4, 5]
},
{
"type": "character",
"attributes": {},
"value": ["a", "b", "c", "d", "e"]
}
]
}
O JSON resultante é mais verboso, mas assegura o retorno ao objeto R original:
utb <- unserializeJSON(sJSON)
class(utb)
[1] "tbl_df" "tbl" "data.frame"
Se quisermos imprimir a tibble:
utb
# A tibble: 5 × 2
a b
* <int> <chr>
1 1 a
2 2 b
3 3 c
4 4 d
5 5 e
Há outros recursos no pacote, como imprimir objetos json de forma bonita (prettify), mas creio que o essencial foi falado. Não se esqueça de ler o tutorial 2, nele mostramos uma infinidade de recursos para trabalhar com JSON.
For attribution, please cite this work as
Filho (2022, Dec. 26). Jurimetria: Json no R - Parte 1. Retrieved from https://direitoemdados.consudata.com.br/posts/2022-12-26-json-no-rparte1/
BibTeX citation
@misc{filho2022json, author = {Filho, José de Jesus}, title = {Jurimetria: Json no R - Parte 1}, url = {https://direitoemdados.consudata.com.br/posts/2022-12-26-json-no-rparte1/}, year = {2022} }