Protocol Buffers (Protobuf) é um formato binário de serialização de dados estruturados, desenvolvido pelo Google para troca eficiente de informações entre serviços. O formato requer definição prévia de esquema em arquivos .proto, a partir dos quais o código é gerado para vários idiomas. De acordo com a documentação oficial do Google, Protobuf fornece tamanhos de mensagem 3-10 vezes menores que JSON. Protobuf é usado em gRPC, Google Maps e milhares de serviços internos.
Principais pontos
Protocol Buffers é um mecanismo de serialização de dados estruturados desenvolvido pelo Google, semelhante a JSON e XML, mas com uma diferença fundamental: os dados são codificados em formato binário. Isso significa que uma mensagem Protobuf não pode ser lida a olho nu, mas ocupa significativamente menos espaço e é processada mais rapidamente que suas contrapartes textuais.
Protobuf foi criado internamente no Google para resolver problemas de desempenho na troca de dados entre serviços. Em 2008, a tecnologia se tornou um projeto de código aberto com suporte para múltiplos idiomas: C++, Java, Python, Go, JavaScript, Kotlin, Swift, Dart e outros. A versão proto3, lançada em 2016, simplificou a sintaxe e adicionou suporte para mais idiomas.
A principal diferença entre Protobuf e JSON é a necessidade de definir um esquema antes do início da troca de dados. O arquivo de esquema (.proto) descreve a estrutura da mensagem: campos, tipos e números únicos de campo. A partir deste esquema, o compilador protoc gera classes no idioma de destino para serialização e desserialização.
A arquitetura do Protobuf inclui três componentes principais: a linguagem de definição de esquema (.proto), o compilador protoc e as bibliotecas de tempo de execução para idiomas específicos. O desenvolvedor descreve a estrutura de dados em um arquivo .proto, executa a compilação e recebe classes prontas para trabalhar com esses dados.
Cada campo em uma mensagem Protobuf tem um número único (field number) — não é um número sequencial, mas uma tag usada no formato binário para identificar o campo. Os números 1 a 15 são codificados em um byte, 16 a 2047 em dois bytes. Portanto, campos importantes com alta frequência de uso devem ser numerados de 1 a 15 para otimizar o tamanho.
Protobuf suporta uma ampla gama de tipos: escalares (int32, int64, float, double, bool, string, bytes), enumerações (enum), compostos (message) e tipos especiais (oneof, map). Cada tipo tem uma representação binária específica otimizada para o caso de uso correspondente.
| Tipo .proto | Tipo C++ | Java/Kotlin | Descrição |
|---|---|---|---|
| double | double | double | Número de ponto flutuante de 64 bits |
| float | float | float | Número de ponto flutuante de 32 bits |
| int32 | int32 | int | 32 bits, codificação de comprimento variável |
| int64 | int64 | long | 64 bits, codificação de comprimento variável |
| string | string | String | String UTF-8 |
| bytes | string | ByteString | Bytes arbitrários |
| bool | bool | boolean | true / false |
Protobuf oferece três vantagens principais sobre os formatos textuais: tamanho da mensagem, velocidade de serialização e tipagem forte. Em sistemas de alta carga e aplicativos móveis com tráfego limitado, essas vantagens se tornam críticas.
A representação binária do Protobuf usa codificação de comprimento variável (Varint) para números: números pequenos ocupam 1 byte, grandes até 10 bytes. Isso permite codificar eficientemente identificadores, flags e contadores que ocupariam dezenas de bytes como strings de texto em JSON ou XML. Por exemplo, o número 150 em Protobuf ocupa 2 bytes, em JSON — 3 bytes (como texto “150”), em XML — 3 bytes + tags.
Uma vantagem adicional é a compatibilidade reversa. Adicionar um novo campo ao esquema não quebra clientes antigos: eles simplesmente ignoram campos desconhecidos. Excluir um campo requer apenas reservar seu número para evitar colisões no futuro.
O esquema .proto descreve a estrutura de dados em uma linguagem especial. O arquivo começa com a especificação da sintaxe (proto3), pacote e dependências de importação. Cada mensagem é definida com a palavra-chave message com campos, onde cada campo tem um tipo, nome e número único.
Boas práticas de esquema: números de campo 1 a 15 para campos usados com frequência, nomes significativos, agrupamento de campos relacionados em uma message separada, uso de oneof para campos que podem ser apenas uma de várias opções.
syntax = "proto3";
package mobileapp;
message User {
string user_id = 1;
string name = 2;
string email = 3;
int32 age = 4;
UserRole role = 5;
repeated string tags = 6;
map<string, string> metadata = 7;
}
enum UserRole {
USER_ROLE_UNSPECIFIED = 0;
USER_ROLE_USER = 1;
USER_ROLE_ADMIN = 2;
USER_ROLE_MODERATOR = 3;
}
As mensagens podem ser aninhadas: um campo profile do tipo Profile conterá dados do usuário internamente. O suporte a aninhamento permite descrever estruturas hierárquicas complexas sem duplicar definições.
syntax = "proto3";
package mobileapp;
message Order {
string order_id = 1;
repeated OrderItem items = 2;
double total_price = 3;
PaymentInfo payment = 4;
}
message OrderItem {
string product_id = 1;
string title = 2;
int32 quantity = 3;
double price = 4;
}
message PaymentInfo {
string method = 1;
string transaction_id = 2;
double amount = 3;
}
O compilador protoc converte arquivos .proto em código fonte no idioma de destino. Para Kotlin/Java usa-se o parâmetro --java_out, para Swift --swift_out (através do plugin Apple Swift Protobuf), para Dart --dart_out. As classes geradas contêm métodos builder para construir mensagens e métodos de serialização/desserialização.
No Android, para trabalhar com Protobuf usa-se o plugin com.google.protobuf versão 0.9+ no Gradle. Após adicionar o plugin e especificar os arquivos .proto, a compilação gera automaticamente classes Kotlin prontas para uso no aplicativo.
import com.google.protobuf.kotlin.toByteString
import com.example.mobileapp.UserOuterClass.User
fun createUser(): User {
return User.newBuilder()
.setUserId("usr_001")
.setName("IT Sectr")
.setEmail("team@itsectr.com")
.setAge(5)
.setRole(UserOuterClass.UserRole.USER_ROLE_ADMIN)
.addTags("mobile")
.addTags("backend")
.build()
}
fun serializeAndDeserialize(user: User): User {
// Serialização para formato binário
val bytes = user.toByteArray()
// Desserialização do formato binário
return User.parseFrom(bytes)
}
Protobuf é especialmente eficaz em arquitetura de microsserviços e aplicativos móveis. Considere um cenário típico: um aplicativo móvel recebe uma lista de produtos do servidor via gRPC. A mensagem Protobuf contém informações do produto incluindo identificador, nome, preço e categoria. O formato binário reduz o tamanho da resposta em 5-8 vezes em comparação com JSON.
Exemplo de um serviço gRPC com Protobuf no lado do servidor. O serviço declara o método RPC GetProducts, que aceita uma solicitação com parâmetros de paginação e retorna uma lista de produtos. A implementação em Kotlin usa classes geradas para trabalhar com solicitações e respostas.
import com.example.mobileapp.ProductServiceGrpcKt
import com.example.mobileapp.ProductOuterClass.Product
import com.example.mobileapp.ProductOuterClass.GetProductsRequest
import com.example.mobileapp.ProductOuterClass.GetProductsResponse
class ProductService : ProductServiceGrpcKt.ProductServiceCoroutineImplBase() {
override suspend fun getProducts(
request: GetProductsRequest
): GetProductsResponse {
val products = fetchProductsFromDb(
page = request.page,
limit = request.limit
)
return GetProductsResponse.newBuilder()
.addAllProducts(products)
.setTotalCount(products.size)
.build()
}
}
A configuração do Protobuf em um projeto Android é feita através do plugin Gradle com.google.protobuf. O plugin executa automaticamente o compilador protoc durante a compilação e gera classes Kotlin a partir de arquivos .proto. Para funcionar, você precisa adicionar o plugin ao build.gradle do projeto e aplicá-lo no módulo do aplicativo.
Após configurar o Gradle, os arquivos .proto são colocados no diretório src/main/proto. O compilador protoc os processa durante cada compilação, gerando classes Kotlin que podem ser usadas no código do aplicativo. É importante especificar corretamente as versões do protobuf e protoc para evitar conflitos de dependência com outras bibliotecas do projeto.
Para projetos iOS, o Protobuf é conectado via CocoaPods ou Swift Package Manager. O plugin Swift Protobuf gera automaticamente estruturas Swift em conformidade com o protocolo Codable. Em projetos Dart para Flutter, o pacote protobuf é usado, e a compilação é feita através de dart run protoc_plugin.
Perguntas frequentes
Protobuf é um formato binário com esquema obrigatório, 3-10 vezes mais compacto que JSON. JSON é textual, legível por humanos e não requer esquema. Protobuf serializa e desserializa mais rápido mas requer compilação de arquivos .proto. JSON é mais fácil de depurar e não requer configuração prévia.
Baixe o protoc do release do GitHub do protobuf para sua plataforma. Para macOS, instale via brew install protobuf. Para Windows, baixe o arquivo zip e adicione protoc.exe ao PATH. Para Android/Kotlin, use o plugin Gradle com.google.protobuf, que executa automaticamente a compilação durante a construção.
gRPC é um framework RPC de alto desempenho do Google que usa Protobuf como linguagem de definição de interface (IDL) e formato de serialização. gRPC define serviços e métodos RPC em arquivos .proto, gera código de cliente e servidor, e suporta streaming e protocolos binários.
Oficialmente suportados pelo Google: C++, Java, Kotlin, Python, Go, Ruby, C#, PHP, JavaScript, Objective-C, Swift e Dart. A comunidade desenvolveu suporte para Rust, TypeScript, Scala, Lua e outros idiomas. Para desenvolvimento móvel, Kotlin/Java (Android) e Swift/Objective-C (iOS) estão disponíveis.
Protobuf suporta compatibilidade reversa através destas regras: não altere os números dos campos, não exclua campos (use reserved), adicione novos campos com novos números. Clientes antigos ignoram campos desconhecidos, novos clientes obtêm valores padrão para campos antigos ausentes.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também