Este post é adaptado de uma comunidade Salesforce Stack Exchange.
O Apex oferece várias formas de realizar a serialização e deserialização de dados em formato JSON. Este post resume os casos de uso e as capacidades da deserialização sem tipo, da (des)serialização tipada, das implementações manuais usando JSONGenerator e JSONParser, e das ferramentas disponíveis para auxiliar esses usos. O objetivo é fornecer uma introdução e uma visão geral das maneiras eficazes de trabalhar com JSON no Apex, bem como links para outros recursos.
📌 Resumo:
O Apex pode serializar e deserializar JSON em classes Apex fortemente tipadas e também em coleções genéricas, como Map e List. Na maioria dos casos, é preferível definir classes Apex que representem estruturas de dados e utilizar a serialização e deserialização tipadas com JSON.serialize()/JSON.deserialize(). No entanto, alguns casos de uso exigem a aplicação de deserialização sem tipo com JSON.deserializeUntyped().
As classes JSONGenerator e JSONParser estão disponíveis para implementações manuais e devem ser usadas apenas quando a (des)serialização automática não for praticável, como quando as chaves no JSON são palavras reservadas no Apex ou quando for necessário um acesso de baixo nível.
As principais referências de documentação são a classe JSON no Guia do Desenvolvedor do Apex e a seção Suporte a JSON. Outros documentos relevantes estão vinculados a partir dessas páginas.
🌟 Tipos Complexos em Apex e JSON:
O JSON oferece mapas (ou objetos) e listas como seus tipos complexos. Listas JSON correspondem a objetos List no Apex. Objetos JSON podem corresponder a classes Apex, com chaves correspondendo a variáveis de instância, ou a objetos Map no Apex. Classes Apex e coleções podem ser combinadas livremente para construir as estruturas de dados corretas para um objetivo JSON específico.
Ao longo deste post, usaremos o seguinte JSON como exemplo:
{
"errors": ["Data failed validation rules"],
"message": "Please edit and retry",
"details": {
"record": "001000000000001",
"record_type": "Account"
}
}
Este JSON inclui dois níveis de objetos aninhados, bem como uma lista de valores primitivos.
🔗 (Des)Serialização Tipada com JSON.serialize() e JSON.deserialize(): Os métodos JSON.serialize()
e JSON.deserialize()
permitem a conversão entre JSON e valores Apex tipados. Essas abordagens são ideais quando você deseja trabalhar com classes Apex bem definidas. Exemplificamos como fazer isso com um exemplo de classe Apex.
public class Exemplo {
public List<String> errors;
public String message;
public class DetalhesExemplo {
Id record;
String record_type;
}
public DetalhesExemplo details;
}
//Para analisar o JSON em uma instância de Exemplo, execute:
Exemplo ex = (Exemplo)JSON.deserialize(jsonString, Exemplo.class);
💡 Deserialização Sem Tipo com JSON.deserializeUntyped(): Em algumas situações, deserializar em coleções de valores primitivos pode ser mais vantajoso do que usar classes fortemente tipadas. É útil quando a estrutura do JSON pode mudar de maneiras imprevisíveis. Abordamos essa técnica usando um exemplo de JSON variável.
O uso do método JSON.deserializeUntyped() gera um valor Object, porque o Apex não sabe em tempo de compilação que tipo de valor o JSON produzirá. Quando se usa esse método, é necessário fazer o tipo de valor consistentemente.
Considere, por exemplo, este JSON, que possui múltiplas variantes marcadas por um valor “escopo”:
{
"scope": "Accounts",
"data": {
"payable": 100000,
"receivable": 40000
}
}
OU
{
"scope": {
"division": "Sales",
"organization": "International"
},
"data": {
"closed": 400000
}
}
JSON de entrada que varia dessa maneira não pode ser manipulado com classes Apex fortemente tipadas porque sua estrutura não é uniforme. Os valores das chaves “scope” e “data” têm tipos diferentes.
Esta estrutura de JSON pode ser desserializada usando JSON.deserializeUntyped(). Esse método retorna um Object, um valor sem tipo cujo tipo real em tempo de execução refletirá a estrutura do JSON. Neste caso, esse tipo seria Map, porque o nível superior de nosso JSON é um objeto. Poderíamos desserializar este JSON da seguinte maneira:
Map<String, Object> resultado = (Map<String, Object>)JSON.deserializeUntyped(jsonString);
A natureza sem tipo do valor que obtemos em retorno se espalha por toda a estrutura, porque o Apex não conhece o tipo em tempo de compilação de nenhum dos valores (que podem, como visto acima, ser heterogêneos) neste objeto JSON.
Portanto, para acessar valores aninhados, devemos escrever código defensivo que inspeciona os valores e faz conversões de tipo em cada nível. O exemplo acima lançará uma TypeException se o tipo resultante não for o esperado.
Para acessar os dados do primeiro elemento no JSON acima, poderíamos fazer algo assim:
Object resultado = JSON.deserializeUntyped(jsonString);
if (resultado instanceof Map<String, Object>) {
Map<String, Object> mapaResultado = (Map<String, Object>)resultado;
if (mapaResultado.get('scope') == 'Accounts' &&
mapaResultado.get('data') instanceof Map<String, Object>) {
Map<String, Object> dados = (Map<String, Object>)mapaResultado.get('data');
if (dados.get('payable') instanceof Integer) {
Integer payable = (Integer)dados.get('payable');
// Faça algo com payable
} else {
// Lidar com erro
}
} else {
// Lidar com erro
}
} else {
// Lidar com erro
}
Embora existam outras maneiras de estruturar esse código, incluindo a captura de exceções JSONException e TypeException, a necessidade de ser defensivo é constante. O código que não é defensivo ao trabalhar com valores sem tipo é vulnerável a mudanças no JSON que geram exceções e modos de falha que não se manifestarão em muitas práticas de teste. Exceções comuns incluem NullPointerException, ao acessar de forma descuidada valores aninhados, e TypeException, ao fazer a conversão de um valor para o tipo errado.
As classes JSONGenerator
e JSONParser
permitem que você construa e analise JSON manualmente. Apresentamos um exemplo prático e ressaltamos que essa abordagem pode ser necessária em casos específicos.
🚀 Gerando Código com JSON2Apex: O JSON2Apex é uma ferramenta poderosa que gera código Apex com base no JSON fornecido. Essa é uma opção útil, especialmente para quem está começando a trabalhar com JSON no Apex.
Ela detecta automaticamente muitas situações em que a análise explícita é necessária e gera código JSONParser para desserializar o JSON em objetos Apex nativos.
O JSON2Apex não resolve todos os problemas relacionados ao uso de JSON, e o código gerado pode exigir revisão e ajuste. No entanto, é um bom ponto de partida para uma implementação, especialmente para usuários que estão começando a usar JSON no Apex.
📚 Recursos Adicionais:
Esperamos que este guia tenha fornecido uma visão abrangente de como trabalhar com JSON no Salesforce. Para mais informações e exemplos, visite nosso site.
#Salesforce #Desenvolvimento #JSON #Apex #Programação #DesenvolvimentoWeb #DicasdeCodificação
👉 Compartilhe seus pensamentos e experiências nos comentários! 👈