Codificação de Caracteres

Como utilizar corretamente os content types e charset no consumo de APIs e integrações.

Quando integramos aplicações através de APIs, é normal se definir um acordo entre o consumidor e provedor no que diz respeito a formatação das mensagens, idiomas e outras regras aceitas por ambas as partes. Esse acordo pode levar em conta padrões de mercado, mas também permitir formatos e criptografias complexas, por questões de segurança.

Os serviços REST criados através do inPaaS atendem requisições em diversos formatos, mas principalmente o formato JSON é utilizado para as mensagens. Para isso, utilizamos o Content Type "application/json" nas mensagem, e assim a nossa API consegue identificar e transformar a mensagem em objetos. Além do JSON, o formato "Form" também é utilizado com o Content-Type "application/x-www-form-urlencoded" e as mensagens também podem ser recebidos normalmente.

No entanto, em algumas mensagens existem acentos, símbolos e caracteres que parecer desconfigurados para o usuário. Normalmente, a causa disso são falhas de codificação (ou Charsets).

Charsets

Sabemos que toda palavra em nosso idioma é traduzida para um formato diferente, mais conhecido como binário. Esses códigos são traduzidos para as letras, e vice-versa, e assim conseguimos enviar e receber mensagens.

No entanto, para esse tradução, é utilizado um dicionário chamado Charset. Esse charset é o que define qual código representa qual letra ou símbolo.

Para caracteres normais(A-Z) normalmente esse código é o mesmo, no entanto, para símbolos e letras acentuadas, esses Charsets podem ter código difererentes:

Veja que a palavra "João" tem uma cadeia de bytes diferentes para cada codificação:

  • ISO-8859-1: 4a 6f e3 6f
  • UTF-8: 4a 6f c3 a3 6f
  • UTF-16: fe ff 00 4a 00 6f 00 e3 00 6f
String.format("%x", new BigInteger(1, "João".getBytes("ISO-8859-1")));
String.format("%x", new BigInteger(1, "João".getBytes("UTF-8")));
String.format("%x", new BigInteger(1, "João".getBytes("UTF-16")));

Isso permite extensibilidade e criação de novos códigos, por exemplo, os famosos "Emojis", que 'há alguns anos não existiam e foram incluídos em novas cadeias de charsets.

Ao tentar ler essa cadeia de bytes usando o encoding errado, você não chegará na palavra "João", e sim, em variações "desformatadas".

Definindo a Codificação

Para evitar problemas nas integrações o ideal é que o requisitante sempre informe o charset (https://www.iana.org/assignments/chpodem parearacter-sets/character-sets.xhtml), além do content-type. Só dessa forma, a plataforma saberá como tratar cada requisição e traduzir corretamente. Conforme exemplos abaixo:

application/json;charset=UTF-8
application/x-www-form-urlencoded;charset=ISO-8859-1
application/x-www-form-urlencoded;charset=UTF-16

Se a requisição for feita com o Content-Type e Charsets declarados corretamente, dificilmente teremos caracteres desconfigurados.

❗️

Problemas de Acentuação

Quando o charset não é declarado, a plataforma tentará ler os dados através de uma conversão implícita, o que pode causar problemas.

Conversão implícita (a fonte do informação não é declarada e a aplicação usará o encoding padrão):
new java.lang.String("olá acentuação".getBytes(), "UTF-8");
olá acentuação

Conversão explícita (você declara explicitamente que tem uma String em ISO-8859-1, converte ela em bytes e depois converte ela novamente para String, agora usando UTF-8:
jjs> new java.lang.String("olá acentuação".getBytes("ISO-8859-1"),"UTF-8");
olá acentuação

Reparem que citamos o ISO-8859-1 e o UTF-8 como origem e destino apenas como exemplo, você deverá avaliar, no seu caso, qual é o encoding correto das suas mensagens e efetuar a integração de acordo.

Updated 3 years ago

Codificação de Caracteres


Como utilizar corretamente os content types e charset no consumo de APIs e integrações.

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.