Introdução
O primeiro post sobre JSON (JavasSript Object Notation) aqui no Blog já faz um bom tempo, foi em Outubro de 2019, e mesmo na época existiam recursos que eu desconhecia. E de lá para cá, esse novo tipo nativo do AdvPL está sendo muito utilizado, mesmo em programas que não tem nenhuma relação com integrações com REST, por ser um objeto prático, rápido, e flexível.
De qualquer modo, a postagem atual não vai repetir toda a introdução ao tipo e suas funcionalidades, mas sim atualizar e complementar as informações dos posts anteriores sobre esse assunto, que servem de base:
- JSON – O que é e como usar em AdvPL
- JSON – O que é e como usar em AdvPL – Parte 02
- JSON – O que é e como usar em AdvPL – Parte 03 – zJsonKit
JSON no TLPP
Um novo objeto do tipo “J” (JSON), tanto em AdvPL como em TLPP, pode ser criado simplesmente usando o construtor do objeto e atribuindo o resultado a uma varíavel:
oJson1 := JsonObject():New()
Uma vez feito isso, podemos popular o objeto em memória a partir de uma string contendo o objeto, ou criar cada novo par de chave X valor usando por exemplo a sintaxe abaixo:
oJson1["Id"] := '001'
oSon1["Chave"] := "Valor"
O mesmo resultado seria também obtido usando o código abaixo:
oJson := JsonObject():New()
oJson:fromJson('{ "ID" : "01" , "Nome" : "Usuário"}')
Agora, o que eu não sabia, é que você pode criar um Objeto Json, inclusive com conteúdo, diretamente em um fonte TLPP, sem o construtor, diretamente através de uma string Json, sem chamar o construtor e o parser.
Se você ainda não sabe ou têm dúvidas sobre o que é o TLPP, dê uma lida na documentação oficial da TOTVS, disponivel aqui. Em breve teremos mais posts aqui dedicados às novidades do TLPP.
Por exemplo, para criar o mesmo objeto JSON do exemplo acima, é possível usar a seguinte sintaxe — dentro de um fonte com extensão TLPP:
oJson := { "ID" : "01" , "Nome" : "Usuário"}
O resultado final será o mesmo: Será criado um objeto JSON, com as propriedades “ID” e “Nome”, respectivamente com os conteúdos “01” e “Usuário”.
Estendendo o exemplo acima, imagine que os valores “01” e “Usuário” estão dentro de duas variáveis do AdvPL, cID e cNome, respectivamente. É possível especificar o valor dinamicamente simplesmente usando a variável, por exemplo:
User Function Json01()
Local oJson
Local cId := '01'
Local cNome := 'Usuário'
oJson := { "ID" : cId , "Nome" : cNome }
msgInfo(oJson:ToJson(),"RESULTADO")
Return
Vale lembrar que, usando a linguagem AdvPL, a linha de código pode ser estendida para a linha de baixo, colocando ‘;’ ponto-e-vírgula no final da linha, então você pode deixar o código mais “legível”, colocando por exemplo apenas duas ou três propriedades em cada linha.
A interpretação de JSON nativo literal somente é compreendida e interpretada em um fonte de extensão TLPP. Se isso for usado dessa forma em um fonte AdvPL, com as extensões padrão (PRG,PRW ou PRX), será exibido um erro de compilação:
Invalid use of Json Syntax in ADVPL source file
NIL x NULL
Uma variável sem valor no AdvPL, é uma variavel nula, ou “NIL”. De forma similar, uma propriedade de um determinado objeto JSON pode existir, mas não ter conteúdo, ou melhor, ter conteúdo “null”. Logo, uma string JSON com uma propriedade “null”, será representado em Advpl com o valor NIL. E vice-versa.
User Function Json02()
Local oJson
Local cId := '01'
oJson := { "ID" : cId , "Nome" : NIL }
msgInfo(oJson:ToJson(),"RESULTADO")
Return
/*
O resultado em tela será a seguinte string :
{"ID":"01","Nome":null}
*/
Ordem das Propriedades
Até o APPServer Build 20.3.0.x , ao criar um objeto JSON, seja criando ele vazio e depois criando e populando suas propriedades, ou criando ele a partir de uma representação JSON em String (caractere), ao exportar novamente o objeto da memória para uma nova String, a ordem das propriedades do objeto não respeitava a ordem de criação das propriedades.
Isso na prática não muda nada no USO do objeto, ele ainda vai conter as propriedades e valores, mas em uma ordem arbitrária, o que dificultava a leitura do objeto. O Primeiro exemplo do post JSON – O que é e como usar em AdvPL – Parte 02 já mostrava isso.
A partir do AppServer Build 20.3.1.0 (Notas de Release AQUI), foi introduzida uma ordenação natural do objeto na memória, partindo da ordem de criação de suas propriedades. Então, ao ler um objeto JSON em String, a ordem é mantida na exportação do objeto, e se ele for manipulado, e novas propriedades forem acrescentadas ao objeto, elas sempre virão no final da string, na ordem em que elas foram criadas. Uma propriedade alterada terá apenas o seu valor alterado, mas a ordem será mantida. Se uma propriedade for removida, e então acrescentada novamente, ela virá para o final.
Dicas e Cuidados
Se eu precisar identificar se um determinado objeto JSON possui uma determinada propriedade, o recomendável é sempre usar o método HasProperty()
Afinal, se eu simplesmente verificar se uma propriedade têm algum conteúdo, existem duas condições diferentes com o mesmo retorno: oJson[“abc”] pode retornar NIL caso a propriedade abc não exista, e também pode retornar NIL caso a propriedade exista, mas seu valor seja NIL.
E, a segunda consideração importantíssima: Ao usar a notação oJson[“propriedade”], mesmo que seja apenas uma consulta, isso cria no objeto a propriedade consultada, com valor NIL. Se o seu programa não vai montar novamente a representação do objeto em String, não há maiores problemas. Mas se este for o caso, cada propriedade consultada que não existia, passa a existir com valor “null” na memória, veja o exemplo abaixo:
User Function Json03()
Local oJson
Local cId := '01'
Local cNome := 'Usuário '
oJson := { "ID" : cId , "Nome" : NIL }
if empty(oJson["Idade"])
// eu estou "consultando" a propriedade "Idade"
MsgInfo("Idade nao encontrada.","ATENÇÃO")
endif
// Agora veja o que acontece com o objeto
// ao exportar para string novamente
// A propriedade "Idade" passou a existir
msgInfo(oJson:ToJson(),"RESULTADO")
Return
O resultado da execução dessa função será primeiro a mensagem que a Idade não foi encontrada, e logo abaixo, a exportar oJson para string novamente, repare que a propriedade “Idade” passou a existir, e com valor “null”

Dito isso, para evitar a criação acidental de propriedades dentro do objeto, se a intenção é apenas verificar se a propriedade existe, procure usar o método HasProperty().
JSON como parâmetro de função
Da mesma forma que um Objeto Advpl (ValueType = “O”) ou um Array (ValueType=”A”), uma variável contendo um objeto JSON (ValueType=”J”), quando informado como parâmetro de uma função, implicitamente passa uma REFERÊNCIA desse objeto. Logo, uma função que recebe uma variavel JSON como parâmetro, pode alterar valores de propriedades, adicionar ou remover propriedades, e isso vai refletir na variável do fonte onde ela foi criada, pois o objeto não foi clonado ou duplicado na memória ao ser passado como parâmetro.
CP1252, UTF8 , Unicode ?
Então, a especificação do formato JSON diz que os caracteres devem ser Unicode, isto é, permitir tudo que é letra de qualquer idioma. A troca de dados dados em ecossistemas normalmente usa a codificação UTF-8, e adicionalmente um caractere também pode usar um escape sequence “\uXXXX”, onde XXXX é o código hexadecimal do caractere na tabela UNICODE.
O mecanismo do AdvPL suporta UTF8, e não faz nenhuma conversão implícita. Isto é, se você está lendo uma string JSON do disco, ou recebeu ela de um REST, onde o nome “Usuário” foi codificado em UTF-8, essa string no Advpl vai ter 8 caracteres, pois no lugar da letra “ú” (u minúsculo com acento agudo), são lidos dois bytes, que representam essa letra na codificação UTF-8 ( ASCII 195 e ASCII 161, respectivamente). Se você precisa dessa string em um codepage CP1252 por exemplo, e essa string contém caracteres que podem ser representados nesse codepage, você deve decodificar a informação usando por exemplo a função DecodeUTF8() do AdvPL
A única conversão implícita feita no parser é automaticamente converter caracteres especificados usando a escape de unicode “\xFFFF” vindas em uma string JSON, para a codificação UTF-8.
Bateu aquela dúvida sobre codificação, encoding e afins ? Têm uma sequência de posts que fala sobre isso:
Conclusão
Como a implementação do JSON precede os recursos do TLPP, seus fundamentos e métodos estão documentados no TDN, dentro das classes AdvPL: https://tdn.totvs.com/display/tec/Classe+JsonObject
A Linguagem AdvPL não parou no tempo, muito pelo contrário, ela está trazendo aos poucos tecnologias, sintaxes e APIS, estendendo mais as capacidades da linguagem. O respeito ao legado e comportamentos esperados são o maior desafio nesse quesito, e é nesse ponto que entra o TL++ (ou TLPP). E isso defintivamente vai render uma sequência de novos posts 😀
E, como de costume, desejo sempre a todos TERABYTES DE SUCESSO !!!
Referências
Todas as referências desse post apontam para a documentação oficial do ADVPL e TLPP, disponibilizada com acesso público no site TDN – Totvs Developer Network, e os posts anteriores sobre JSON e Encoding publicados aqui no Blog.







































