Trabalhando com JSON Aninhado em Delphi

JSON Aninhado em Delphi
JSON

Introdução

Nesse post trataremos sobre JSON Aninhado em Delphi.

O JSON (JavaScript Object Notation) é amplamente utilizado para representar e transmitir dados em aplicações modernas devido à sua simplicidade e legibilidade. Em Delphi, a manipulação de JSON é essencial, especialmente quando se trata de trabalhar com estruturas JSON aninhadas. Neste artigo, exploraremos como criar, manipular e acessar dados em objetos JSON complexos utilizando Delphi, destacando as boas práticas e fornecendo exemplos de código.

1. Criando Estruturas JSON Aninhadas

Antes de abordar a manipulação, é importante entender como criar uma estrutura JSON aninhada. Uma estrutura JSON aninhada contém objetos ou arrays dentro de outros objetos. Isso é útil para representar dados hierárquicos ou complexos.

Em Delphi, o componente TJSONObject é usado para criar objetos JSON, enquanto TJSONArray é utilizado para criar arrays. Vamos começar com um exemplo simples de criação de um JSON aninhado que representa um pedido de compra:

uses
  System.JSON;

procedure CriarJSONAninhado;
var
  Pedido: TJSONObject;
  Cliente, Endereco: TJSONObject;
  Itens: TJSONArray;
begin
  Pedido := TJSONObject.Create;
  try
    Cliente := TJSONObject.Create;
    Cliente.AddPair('Nome', 'João Silva');
    Cliente.AddPair('CPF', '123.456.789-00');

    Endereco := TJSONObject.Create;
    Endereco.AddPair('Rua', 'Av. Paulista');
    Endereco.AddPair('Número', '1000');
    Endereco.AddPair('Cidade', 'São Paulo');
    Endereco.AddPair('Estado', 'SP');
    Cliente.AddPair('Endereco', Endereco);

    Pedido.AddPair('Cliente', Cliente);

    Itens := TJSONArray.Create;
    Itens.AddElement(TJSONObject.Create.AddPair('Produto', 'Notebook').AddPair('Quantidade', '1').AddPair('Valor', '3500'));
    Itens.AddElement(TJSONObject.Create.AddPair('Produto', 'Mouse').AddPair('Quantidade', '2').AddPair('Valor', '150'));

    Pedido.AddPair('Itens', Itens);

    // Saída do JSON
    ShowMessage(Pedido.ToString);
  finally
    Pedido.Free;
  end;
end;

Neste exemplo, criamos um objeto JSON que representa um pedido com informações de cliente, endereço e itens de compra. Observe que o objeto Cliente contém um objeto aninhado Endereco, e Pedido contém um array Itens, que por sua vez contém objetos JSON.

Veja como ficará o JSON:

{
  "Cliente":{
    "Nome":"João Silva",
    "CPF":"123.456.789-00",
    "Endereco":{
       "Rua":"Av. Paulista",
       "Número":"1000",
       "Cidade":"São Paulo",
       "Estado":"SP"
    }
  },
  "Itens":[
    {
      "Produto":"Notebook",
      "Quantidade":"1",
      "Valor":"3500"
    },
    {
      "Produto":"Mouse",
      "Quantidade":"2",
      "Valor":"150"
    }
  ]
}

2. Manipulando Estruturas JSON Aninhadas

Uma vez criada a estrutura JSON, é comum precisar manipular ou atualizar seus dados. Vamos imaginar que o cliente mudou de endereço e precisamos atualizar essa informação.

uses
  System.JSON;

procedure AtualizarEndereco(Pedido: TJSONObject);
var
  Cliente, NovoEndereco: TJSONObject;
begin
  Cliente := Pedido.GetValue<TJSONObject>('Cliente');
  if Assigned(Cliente) then
  begin
    NovoEndereco := TJSONObject.Create;
    try
      NovoEndereco.AddPair('Rua', 'Rua Nova');
      NovoEndereco.AddPair('Número', '500');
      NovoEndereco.AddPair('Cidade', 'Rio de Janeiro');
      NovoEndereco.AddPair('Estado', 'RJ');

      Cliente.RemovePair('Endereco'); // Remove o endereço antigo
      Cliente.AddPair('Endereco', NovoEndereco); // Adiciona o novo endereço
    except
      NovoEndereco.Free;
      raise;
    end;
  end;
end;

Neste código, utilizamos o método GetValue<TJSONObject> para acessar o objeto Cliente e, em seguida, atualizamos o endereço do cliente com um novo objeto JSON.

3. Acessando Dados em Objetos JSON Aninhados

A leitura de dados de um JSON aninhado é igualmente importante. Vamos ver como acessar os dados do JSON criado anteriormente.

procedure LerDadosDoPedido(Pedido: TJSONObject);
var
  Cliente: TJSONObject;
  NomeCliente: string;
  Endereco: TJSONObject;
  Cidade: string;
begin
  Cliente := Pedido.GetValue<TJSONObject>('Cliente');
  if Assigned(Cliente) then
  begin
    NomeCliente := Cliente.GetValue<string>('Nome');
    ShowMessage('Nome do Cliente: ' + NomeCliente);

    Endereco := Cliente.GetValue<TJSONObject>('Endereco');
    if Assigned(Endereco) then
    begin
      Cidade := Endereco.GetValue<string>('Cidade');
      ShowMessage('Cidade: ' + Cidade);
    end;
  end;
end;

Neste exemplo, acessamos o nome do cliente e a cidade do endereço, utilizando GetValue<T> para obter os valores específicos de cada chave. É importante sempre verificar se o objeto ou array foi encontrado antes de tentar acessar seus valores, para evitar exceções.

4. Passo a Passo

Passo 1: Configuração Inicial
  1. Crie um novo projeto VCL no Delphi:
    • Selecione File > New > VCL Forms Application – Delphi.
    • Salve o projeto com o nome sugerido pelo Delphi para facilitar o exemplo.
    • Salve a unit do formulário com o nome sugerido Delphi para facilitar o exemplo.
  2. Adicione Componentes ao Formulário:
    • Adicione 3 botões (TButton) no topo do formulário para acessar os métodos de criação, manipulação e leitura do JSON.
    • Adicione uma caixa de texto (TMemo) para exibir o JSON criado.
Passo 2: Declare o uso da biblioteca System.JSON
Uses System.JSON;
Passo 3: Defina a variável Pedido

A variável pedido precisa ser declarada na classe do formulário, como privada, para poder ser acessada em todos os métodos da classe.

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Memo1: TMemo;
  private
    Pedido: TJSONObject; //Variável Pedido que será acessada por todos os métodos que serão criados
    { Private declarations }
  public
    { Public declarations }
  end;
Passo 4: Definição do métodos

Iremos criar os métodos CriarJSONAninhado, AtualizarEndereco(Pedido: TJSONObject), LerDadosDoPedido(Pedido: TJSONObject), Button1Click, Button2Click, Button3Click, FormCreate e FormDestroy.

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    Pedido: TJSONObject; //Variável Pedido que será acessada por todos os métodos que serão criados
    procedure CriarJSONAninhado;
    procedure AtualizarEndereco(Pedido: TJSONObject);
    procedure LerDadosDoPedido(Pedido: TJSONObject);
    { Private declarations }
  public
    { Public declarations }
  end;

Os métodos dos botões serão responsáveis por acionar os métodos de criação, atualização e leitura.

O métodos FormCreate e FormDestroy serão responsáveis por inicializar e liberar da memória a variável Pedido.

Passo 5: Código completo
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.JSON;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    Pedido: TJSONObject; //Variável Pedido que será acessada por todos os métodos que serão criados
    procedure CriarJSONAninhado;
    procedure AtualizarEndereco(Pedido: TJSONObject);
    procedure LerDadosDoPedido(Pedido: TJSONObject);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  CriarJSONAninhado;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  AtualizarEndereco(Pedido);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  LerDadosDoPedido(Pedido);
end;

procedure TForm1.CriarJSONAninhado;
var
  Cliente, Endereco: TJSONObject;
  Itens: TJSONArray;

begin
  if not Assigned(Pedido) then
    Exit;

  Cliente := TJSONObject.Create;
  Cliente.AddPair('Nome', 'João Silva');
  Cliente.AddPair('CPF', '123.456.789-00');

  Endereco := TJSONObject.Create;
  Endereco.AddPair('Rua', 'Av. Paulista');
  Endereco.AddPair('Número', '1000');
  Endereco.AddPair('Cidade', 'São Paulo');
  Endereco.AddPair('Estado', 'SP');
  Cliente.AddPair('Endereco', Endereco);

  Pedido.AddPair('Cliente', Cliente);

  Itens := TJSONArray.Create;
  Itens.AddElement(TJSONObject.Create.AddPair('Produto', 'Notebook').AddPair('Quantidade', '1').AddPair('Valor', '3500'));
  Itens.AddElement(TJSONObject.Create.AddPair('Produto', 'Mouse').AddPair('Quantidade', '2').AddPair('Valor', '150'));

  Pedido.AddPair('Itens', Itens);

  Memo1.Clear;
  // Saída do JSON
  Memo1.Lines.Add(Pedido.ToString);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Pedido := TJSONObject.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(Pedido) then
    Pedido.Free;
end;

procedure TForm1.AtualizarEndereco(Pedido: TJSONObject);
var
  Cliente, NovoEndereco: TJSONObject;
begin
  Cliente := Pedido.GetValue<TJSONObject>('Cliente');
  if Assigned(Cliente) then
  begin
    NovoEndereco := TJSONObject.Create;
    try
      NovoEndereco.AddPair('Rua', 'Rua Nova');
      NovoEndereco.AddPair('Número', '500');
      NovoEndereco.AddPair('Cidade', 'Rio de Janeiro');
      NovoEndereco.AddPair('Estado', 'RJ');

      Cliente.RemovePair('Endereco'); // Remove o endereço antigo
      Cliente.AddPair('Endereco', NovoEndereco); // Adiciona o novo endereço
      Memo1.Clear;
      Memo1.Lines.Add(Cliente.ToString);
    except
      NovoEndereco.Free;
      raise;
    end;
  end;
end;

procedure TForm1.LerDadosDoPedido(Pedido: TJSONObject);
var
  Cliente: TJSONObject;
  NomeCliente: string;
  Endereco: TJSONObject;
  Cidade: string;

begin
  Cliente := Pedido.GetValue<TJSONObject>('Cliente');
  Memo1.Clear;
  if Assigned(Cliente) then
  begin
    NomeCliente := Cliente.GetValue<string>('Nome');
    Memo1.Lines.Add('Nome do Cliente: ' + NomeCliente);

    Endereco := Cliente.GetValue<TJSONObject>('Endereco');
    if Assigned(Endereco) then
    begin
      Cidade := Endereco.GetValue<string>('Cidade');
      Memo1.Lines.Add('Cidade: ' + Cidade);
    end;
  end;
end;

end.

Veja abaixo a ilustração do projeto:

Ilustração do projeto.

Código fonte do exemplo

Você pode fazer o download do exemplo do projeto através do repositório do github:

https://github.com/Gisele-de-Melo/JSON_Aninhado

5. Boas Práticas

  • Verificação de Nulos: Sempre verifique se os objetos ou arrays JSON existem antes de acessá-los para evitar exceções.
  • Uso de Try-Finally: Quando criar objetos JSON manualmente, utilize blocos try-finally para garantir que a memória seja liberada corretamente.
  • Validação de JSON: Antes de manipular JSON, valide a estrutura e a conformidade com o esperado para evitar erros de acesso a dados.
  • Tratamento de Exceções: Ao trabalhar com dados JSON, use blocos try-except para capturar e tratar exceções que possam ocorrer durante a manipulação.

Conclusão

Trabalhar com JSON aninhado em Delphi é uma habilidade essencial para desenvolvedores que lidam com aplicações que envolvem dados complexos. Neste artigo, abordamos como criar, manipular e acessar dados em estruturas JSON aninhadas, utilizando boas práticas que garantem a robustez do código. Ao seguir essas diretrizes, você estará bem equipado para lidar com qualquer desafio relacionado ao JSON em suas aplicações Delphi.

Posts Relacionados


Livros + e-books

Delphi para Android e iOS

codedelphi.com
codedelphi.com

Delphi Start

codedelphi.com

Programando em Delphi XE

Aprenda programar Delphi

Banco de Dados RAD Delphi

Delphi Programming Projects

Deixe um comentário