Pular para o conteúdo

Comunicação de Dados

Este material complementa os slides do Tópico 12 e aprofunda a comunicação de dados entre sistemas: como objetos são convertidos em formatos textuais, como JSON e XML são estruturados e como o Spring/Jackson realizam o Object Mapping.

Enquanto o HTTP define como as mensagens trafegam, este tópico trata do formato dessas mensagens — o que permite que aplicações escritas em linguagens diferentes se entendam.

Um objeto Java na memória existe apenas dentro daquela máquina e daquele processo. Ele não pode ser enviado “cru” pela rede para uma aplicação escrita em outra linguagem.

Para integrar sistemas, é preciso:

  • um formato padronizado, independente de linguagem e plataforma;
  • um processo de conversão com custo computacional aceitável;
  • regras claras de representação de tipos (texto, número, lista, booleano, nulo).
  • Serialização: converter um objeto em memória para um formato (texto ou bytes) que possa ser armazenado ou transferido.
  • Desserialização: o processo inverso, reconstruindo o objeto a partir do dado serializado.

Esse par de operações acontece o tempo todo em uma API: o corpo JSON de uma requisição é desserializado em um objeto Java; o objeto de resposta é serializado de volta para JSON.

O formato escolhido impacta tamanho, legibilidade, velocidade e ferramentas disponíveis.

Existem diversos formatos para troca de dados:

  • JSON — leve, textual, dominante em APIs REST modernas;
  • XML — flexível, com suporte a atributos e esquemas, comum em SOAP e sistemas corporativos;
  • YAML — legível, muito usado em arquivos de configuração;
  • CSV — simples, adequado a dados tabulares;
  • HTML — dados estruturados para exibição na Web;
  • GeoJSON — dados geoespaciais;
  • MessagePack — formato binário compacto para alta performance.
Formato Tipo Verbosidade Uso típico
JSON Texto Baixa APIs REST, mobile
XML Texto Alta SOAP, integrações corporativas
YAML Texto Baixa Configuração
CSV Texto Muito baixa Planilhas, exportações
MessagePack Binário Muito baixa Alta performance

O JSON (JavaScript Object Notation) é um formato de troca de dados em modo texto baseado na notação de objetos do JavaScript.

  • Independente de linguagem de programação;
  • Sintaxe simples e textual;
  • Fácil de ler por humanos e de processar por máquinas.
  • Dados são encapsulados em pares chave: valor;
  • Pares são separados por ,;
  • Objetos são delimitados por { };
  • Vetores (listas) são delimitados por [ ];
  • As chaves são sempre strings entre " ".

Um objeto vazio é representado por {}. Um par simples, por { "usuarios" : "john e mary" }.

O JSON suporta:

  • Strings — "cem";
  • Números — 100, 100.0, 1.0E+2;
  • Objeto — { "cem" : 100 };
  • Vetor — [100, 100.1, "cem"];
  • Booleano — true ou false;
  • Nulo — null.

Não existem tipos nativos para funções, datas ou void. Datas, por exemplo, costumam ser representadas como texto no padrão ISO 8601 ("2030-08-06T01:31:51Z").

{
"usuarios": {
"john": {
"email": "john@matrix.com",
"senha": "12345"
},
"mary": {
"email": "m.mary@bol.com.br",
"senha": "abc123",
"admin": true
}
}
}

O XML (eXtensible Markup Language) representa dados por meio de tags hierárquicas.

  • Suporta atributos (ex.: id="10");
  • Suporta namespaces (ex.: xmlns) para evitar conflito de nomes;
  • É a base de protocolos como o SOAP.
<?xml version="1.0" encoding="UTF-8"?>
<produto id="10">
<nome>Teclado</nome>
<preco>199.90</preco>
<categorias>
<categoria>Periféricos</categoria>
<categoria>Acessórios</categoria>
</categorias>
</produto>
  • Bem-formado: segue a sintaxe XML (tags fechadas, aninhamento correto);
  • Válido: além de bem-formado, respeita um esquema (XSD), garantindo contrato e tipos.
Critério JSON XML
Verbosidade Baixa Alta
Estrutura Objetos e listas Tags hierárquicas
Validação por esquema JSON Schema XSD
Tipos nativos Sim (número, booleano, null) Não (tudo texto)
Uso comum APIs REST SOAP, integrações corporativas

Object Mapping é a conversão entre representações textuais (JSON/XML) e objetos da aplicação.

  • O objeto mapeado costuma ser um POJO (Plain Old Java Object);
  • Cada campo do objeto corresponde a uma chave no JSON;
  • Anotações ajustam nomes, formatos e campos ignorados.
public class Produto {
private UUID id;
private String nome;
private double preco;
// getters e setters...
}
public class Produto {
@JsonProperty("product_name")
private String nome;
@JsonIgnore
private String senhaInterna;
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate dataCriacao;
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean promocao;
}
  • @JsonProperty: define o nome usado no JSON;
  • @JsonIgnore: omite o campo na serialização;
  • @JsonFormat: controla formatos (datas, números);
  • @JsonInclude: omite o campo do JSON quando seu valor é null (ou vazio).

O Jackson é a biblioteca de serialização/desserialização usada por padrão no Spring Boot. Suas classes centrais incluem o ObjectMapper.

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(produto);
Produto p = mapper.readValue(json, Produto.class);
  • Formato de datas: define como as datas são (de)serializadas;
  • Inclusão/omissão de null: evita enviar campos nulos no JSON;
  • Estratégia de nomes (snake_case, camelCase): padroniza nomes de campos;
  • Falha (ou não) em campos desconhecidos: controla o comportamento quando campos não esperados são encontrados.
spring.jackson.serialization.indent-output=true
spring.jackson.default-property-inclusion=non_null
@PostMapping("/login")
public ResponseEntity<Object> login(@RequestBody Login login) {
Boolean ok = login.getUsuario().equals("ronaldinho")
&& login.getSenha().equals("bruxo123");
if (ok) {
return ResponseEntity.ok("Login realizado com sucesso");
}
return ResponseEntity.status(401).body("Senha ou usuário incorreto");
}

O Spring usa o Accept/Content-Type e o Jackson para converter o corpo da requisição em um objeto (Login).

Com @RestController o objeto retornado é serializado automaticamente:

@GetMapping("/produto")
public Produto gerar() {
return new Produto(UUID.randomUUID(), "Teclado", 199.90);
}

Resposta:

HTTP/1.1 200 OK
Content-Type: application/json
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "nome": "Teclado", "preco": 199.9 }

O mesmo recurso pode ser devolvido em formatos diferentes, conforme o Accept:

@GetMapping(value = "/produto",
produces = { MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE })
public Produto detalhar() {
return new Produto(UUID.randomUUID(), "Teclado", 199.90);
}

Para responder XML, adicione a dependência jackson-dataformat-xml:

<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>

Com a mesma dependência, o @RequestBody também desserializa XML quando o Content-Type da requisição é application/xml:

@PostMapping(consumes = { MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_XML_VALUE })
public Produto criar(@RequestBody Produto produto) {
return produtoRepository.save(produto);
}
POST /produtos HTTP/1.1
Content-Type: application/xml
<Produto>
<nome>Mouse</nome>
<preco>89.90</preco>
</Produto>
  • Padronizar as mensagens de sucesso e de erro;
  • Usar DTOs em vez de expor entidades diretamente;
  • Evitar expor dados sensíveis na serialização (@JsonIgnore);
  • Definir corretamente Content-Type e Accept;
  • Preferir JSON para APIs REST, reservando XML para casos que o exijam.

Até aqui tratamos do formato das mensagens. Vale registrar uma distinção importante: cache HTTP e cache de aplicação são mecanismos diferentes, que atuam em pontos diferentes.

Cache HTTP Cache de aplicação
Onde atua Cliente, proxy ou CDN Dentro do servidor
Como é controlado Cabeçalhos (Cache-Control, ETag) Código/anotações
O que evita Transferência desnecessária pela rede Reprocessamento e consultas ao banco
Validação If-None-Match → 304 Not Modified Chave de cache → hit / miss

O cache HTTP foi visto no Tópico 11 e é o cobrado na Atividade 09. Já o cache de aplicação é implementado pelo próprio servidor para não repetir trabalho — por exemplo, com o Spring Cache:

@SpringBootApplication
@EnableCaching
public class Application { ... }
@RestController
public class ProdutoController {
@Cacheable("produtos")
@GetMapping("/{id}")
public Produto getProduto(@PathVariable UUID id) {
return produtoRepository.findById(id).get();
}
}

Por baixo dos panos, o Spring usa um CacheManager; sem um provedor configurado, ele guarda os valores em memória (um ConcurrentHashMap). Esse é apenas um primeiro contato: cache distribuído (ex.: Redis) e escalabilidade serão aprofundados em outro tópico.

Neste tópico você viu por que aplicações precisam de formatos padronizados de troca de dados e como a serialização e a desserialização tornam possível a comunicação entre sistemas.

Entender JSON, XML e o Object Mapping com o Jackson é essencial para projetar APIs previsíveis, controlar o que é exposto e integrar-se corretamente com clientes web e mobile.