JSON – O que é e como usar em AdvPL

Introdução

Em alguns tópicos anteriores, mencionei um formato de representação de objetos chamado JSON — acrônimo de JavaScript Object Notation. Bem, está na hora de ver um pouco mais sobre o que é isso e como funciona 😀

O que é JSON

JSON é uma forma de representação de objetos (e dados) em texto, com separadores e delimitadores. Em linhas gerais, todas as representações de dados em arquivo texto com algum tipo de estruturação usa separadores e delimitadores, como por exemplo XML e derivados … a diferença básica está na simplicidade.

A especificação do formato JSON é independente de linguagem ou plataforma, mas usa “convenções” (símbolos e terminologias) familiares aos programadores de linguagens da família “C” ( C, C++, C#, Java, JavaScript).  Ela parte da representação de uma informação qualquer (VALOR), identificada por um nome (CHAVE), no formato CHAVE : VALOR, onde o VALOR é a informação em si, que pode ser:

  • uma string  / texto
  • um número
  • um booleano ( true ou false )
  • null ( ou nulo )
  • um objeto 
  • um array (ou lista)

A sacada está nos dois últimos tipos de valores, que atuam como “agrupadores” de valores. Os tipos básicos de um valor são apenas os quatro primeiros. Um objeto contem um agrupamento de CHAVE=VALOR delimitado por chaves “{ }” e separados por vírgula, enquanto um array ou lista é delimitado por colchetes “[ ]” e pode conter qualquer um dos valores acima separados por vírgula.

Podemos representar um objeto “vazio” como  { } , um objeto com uma propriedade chamada nome com valor nulo como  { “nome”: null } , um objeto com duas propriedades , onde uma delas é um número e outra um array de números como { “p1”: 0, “p2”: [1,2,3] } e assim por diante.

Um valor string (ou texto) deve ser delimitado por aspas duplas, e pode conter qualquer sequência de bytes dentro dela, exceto uma aspa dupla (“) ou uma barra inversa ( \ ), que caso façam parte do conteúdo, podem ser representados respectivamente como  \” \\ . Um nome que representa uma chave deve ser uma string, um número pode ser representado com parte decimal separada por “.” ponto e até mesmo usar notação científica, e os valores true, false e null são representados exatamente assim como está escrito. Um array é delimitado por colchetes, pode ter nenhum, um ou mais valores (chamados de “elementos”), onde cada elemento pode ser um valor de qualquer tipo, inclusive objeto ou array — arrays encadeados ou multidimensionais.

Onde esse formato é usado ?

A especificação JSON é usada em APIs de troca de dados e processamento (SOA), como por exemplo os WebServices REST, o banco de dados MongoDB foi feito para armazenar, recuperar e manipular objetos JSON, arquivos de configuração de diversas aplicações e projetos, o céu é o limite — pergunte pro Google, JSON é usado em uma ampla gama de implementações, ferramentas e plataformas.

Dá para usar JSON para uma infinidade de tarefas, mas lembre-se que ele não é “bala de prata”, para cada tamanho de problema e necessidade, existem alternativas que se encaixam perfeitamente ou atendem melhor… Tudo depende do tamanho e especificação da sua necessidade, e como você a implementa.

JSON no AdvPL

Para ler, manipular e gerar uma string com JSON, a linguagem AdvPL fornece uma classe chamada JsonObject — vide link da TDN no final do post — e uma sintaxe no AdvPL que permite um enumerador de array do tipo “C” Caractere no AdvPL. Vamos ver como utilizá-la inicialmente para obter o conteúdo de um arquivo JSON, usando o arquivo de exemplo abaixo — podemos salvá-lo como “exemplo1.json”:

{ 
  "Id": 123456,
  "Nome": "Joanilson Wesley",
  "Alergias": [ "Aspirina","Paracetamol" ],
  "Dependentes": false,
  "Outros": {
    "Sangue": "A+",
    "Eleitor": true,
    "Reservista": true
  }
}

Exemplo de Leitura em AdvPL

Este arquivo contém um objeto, com as propriedades “Id” (numérica, valor 123456), “Nome” (string, valor “Joanilson Wesley”), “Alergias” (array de strings, contendo os valores “Aspirina” e “Paracetamol”), e a propriedade “Dependentes” com valor false, e a propriedade Outros contém um novo objeto com três propriedades. Partindo da premissa que este é o formato conhecido e padrão deste objeto, para obter os valores das propriedades deste JSON em AdvPL, podemos fazer o seguinte:

User Function Exemplo1()
Local cFile := '\teste\exemplo1.json'
Local cJsonStr,oJson
Local nId, cNome, lDepend, aAlerg
Local oOutros, cTipoS, lEleitor, lReserv

// Le a string JSON do arquivo do disco 
cJsonStr := readfile(cFile)

// Cria o objeto JSON e popula ele a partir da string
oJson := JSonObject():New()
cErr  := oJSon:fromJson(cJsonStr)

If !empty(cErr)
  MsgStop(cErr,"JSON PARSE ERROR")
  Return
Endif

// Agora vamos ler as propriedades com GetJSonObject()

nId := oJson:GetJSonObject('Id')
cNome := oJson:GetJSonObject('Nome')
lDepend := oJson:GetJSonObject('Dependentes')

// Aqui será retornado um array de strings
aAlerg := oJson:GetJSonObject('Alergias')
cAlerg1 := aAlerg[1]
cAlerg2 := aAlerg[2]

// Objeto dentro de uma propriedade
oOutros := oJson:GetJSonObject('Outros')

cTipoS := oOutros:GetJSonObject('Sangue')
lEleitor := oOutros:GetJSonObject('Eleitor')
lReserv := oOutros:GetJSonObject('Reservista')

// Descarta o objeto 
FreeObj(oJson)

Return

Comportamentos e pontos de atenção

  • Embora na orientação a objetos do AdvPL, uma instância de uma classe possui o tipo “O” (Object), para o JSON o tipo do objeto retornado é “J” — JSON Object— verificamos o tipo do conteúdo de uma variável AdvPL usando a função ValType().
  • O método GetJsonObject() recupera o conteúdo de qualquer propriedade, já realizando a “conversão” da informação para um tipo AdvPL. Por exemplo, uma propriedade contendo uma string retorna uma variável do tipo “C” (Caractere) do AdvPL, um valor booleano retorna .T. ou .F., um valor numérico retorna um tipo “N” numérico em AdvPL, um Array retorna um “A” Array mesmo, e uma propriedade retorna uma instância de objeto JSON.
  • Os nomes das chaves informadas o método GetJsonObject() são “case sensitive” (letras maiúsculas são diferentes de minúsculas). Caso seja solicitado um valor cujo identificador não exista no JSON, o método retorna NIL.

Sintaxe mais amigável

Um Objeto JSON em AdvPL permite acessar as suas propriedades de uma forma mais “elegante”, veja no exemplo abaixo:

// Ao invés de
nId := oJson:GetJsonObject('Id')
// Você pode utilizar
nId := oJson['Id']

// As recuperações dos valores do exemplo acima 
// poderiam ser escritas assim:

nId := oJson['Id']
cNome := oJson['Nome']
lDepend := oJson['Dependentes']
cAlerg1 := oJson['Alergias'][1]
cAlerg2 := oJson['Alergias'][2]
cTipoS := oJson['Outros']['Sangue']
lEleitor := oJson['Outros']['Eleitor']
lReserv := oJson['Outros']['Reservista']

Esta sintaxe é mais “clean“, e permite encadeamentos de forma simples. Mas lembre-se que um acesso a uma propriedade que não existe retorna NIL, e se você não verifica o retorno e usa um encadeamento, o próximo nível de encadeamento fatalmente vai apresentar um erro de execução. Se o array de alergias somente tiver um elemento, acessar o elemento vai encerrar o processo com um erro Array out of bounds. O encadeamento oJson[‘Outros’][‘Reservista’] será finalizado com um erro “Variable is not a array” caso a propriedade ‘Outros’ não exista.

Demais métodos

Um método interessante é o GetNames() — ele retorna um array de strings em Advpl, contendo o nome das propriedades de um objeto JSON. Com ele você pode enumerar e acessar todas as propriedades de um objeto JSON mesmo sem saber o seu nome.

Considerações importantes

Um ponto importante a ser lembrado é o seguinte: O formato JSON como um objeto sempre parte da representação de um OBJETO — começa com “{” abertura de chaves, deve ter pelo menos uma propriedade e um valor, e encerra com “}”. Você pode ter um arquivo em disco com múltiplas linhas, onde cada linha tem um objeto JSON — por exemplo representando um registro de uma tabela — mas isso não é um ARRAY de Objetos — são objetos independentes, um por linha. Ao ler um arquivo formatado dessa forma, cada linha deve ser tratada como um objeto independente, e não simplesmente ler o arquivo inteiro e jogar para o parser. O Parser vai entender e avaliar apenas a primeira linha. Ele somente será um array de objetos se houver um objeto JSON de nível superior, com uma propriedade declarada com um array, onde as demais linhas serão elementos desse array, devidamente separados por vírgula.

Conclusão

É mais simples do que a gente imagina antes de conhecer, e muito prático para uso. Não é a toa que ele é muito utilizado 😀 Para continuar lendo sobre esse assunto, acesse o próximo post — JSON – O que é e como usar em AdvPL – Parte 02 — onde veremos como alterar e acrescentar propriedades no objeto JSON.

Agradeço novamente a audiência, espero que este conhecimento lhe seja útil, e lhes desejo TERABYTES DE SUCESSO !!!

Referências

 

7 comentários sobre “JSON – O que é e como usar em AdvPL

  1. Julio, excelente post, utilizei basicamente a classe que utilizou para recuperar cotação de moedas, porém não consigo extrair nem as chaves e nem o conteúdo na na ‘value’, este é o Json:
    {“@odata.context”:”https://was-p.bcnet.bcb.gov.br/olinda/servico/PTAX/versao/v1/odata$metadata#_CotacaoMoedaDia”,”value”:[{“paridadeCompra”:1.00000,”paridadeVenda”:1.00000,”cotacaoCompra”:4.24790,”cotacaoVenda”:4.24850,”dataHoraCotacao”:”2019-11-27 10:11:20.069″,”tipoBoletim”:”Abertura”},{“paridadeCompra”:1.00000,”paridadeVenda”:1.00000,”cotacaoCompra”:4.26000,”cotacaoVenda”:4.26060,”dataHoraCotacao”:”2019-11-27 11:05:17.297″,”tipoBoletim”:”Intermediário”},{“paridadeCompra”:1.00000,”paridadeVenda”:1.00000,”cotacaoCompra”:4.26660,”cotacaoVenda”:4.26720,”dataHoraCotacao”:”2019-11-27 12:11:18.316″,”tipoBoletim”:”Intermediário”},{“paridadeCompra”:1.00000,”paridadeVenda”:1.00000,”cotacaoCompra”:4.26400,”cotacaoVenda”:4.26460,”dataHoraCotacao”:”2019-11-27 13:09:31.444″,”tipoBoletim”:”Intermediário”},{“paridadeCompra”:1.00000,”paridadeVenda”:1.00000,”cotacaoCompra”:4.25960,”cotacaoVenda”:4.26020,”dataHoraCotacao”:”2019-11-27 13:09:31.449″,”tipoBoletim”:”Fechamento PTAX”}]}

    Curtido por 1 pessoa

    • Opa, beleza ? Obrigado …rs… Então, a propriedade ‘value’ é um array de objetos JSON. Você acessa ele em AdvPL como um array normal, veja o exemplo abaixo — montado para ler as cotações :

      USER Function JMoedas()
      Local cStr, oJson, nI
      Local aValues

      cStr := memoread(‘\moedas.txt’)
      oJson := JSonObject():New()
      oJson:fromJson(cStr)

      aValues := oJson[‘value’]

      For nI := 1 to len(aValues)
      conout(‘Cotacao ‘+cValToChar(nI)+”/”+cValToChar(len(aValues)))
      conout(aValues[nI][‘paridadeCompra’])
      conout(aValues[nI][‘paridadeVenda’])
      conout(aValues[nI][‘cotacaoCompra’])
      conout(aValues[nI][‘cotacaoVenda’])
      conout(aValues[nI][‘tipoBoletim’])
      Next

      Return

      Curtir

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s