Google nos ofrece este sencillo método para tratar estructuras de datos serializadas y olvidarnos del lenguaje utilizado y de la plataforma en la que se vaya a ejecutar.
Índice de contenidos
- 1. Introducción
- 2. Entorno
- 3. Estructura de un mensaje
- 4. Enumerados
- 5. Mensajes como tipo
- 6. Compilando
- 7. Conclusiones
- 8. Referencias
1. Introducción
Protocol Buffers es un mecanismo de Google para serializar estructuras de datos independientes a la plataforma y al lenguaje, que luego podremos compilar al lenguaje que utilicemos en nuestra aplicación, obteniendo a la vez métodos de lectura y escritura de los mismos. En este tutorial, veremos cómo crear nuestras estructuras utilizando proto3, la última versión del protocolo.
2. Entorno
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro Retina 15′ (2,2 Ghz Intel Core i7, 16GB DDR3).
- Sistema Operativo: Mac OS High Sierra 10.13
- Compilador de Protocol Buffers: protoc 3.5.1 (versión precompilada para MacOS)
3. Estructura de un .proto
La extensión de archivo que se utiliza es .proto, y dentro de ellos, la unidad principal para los registros de datos es el message, que contiene pares nombre-valor con los atributos que queremos incluir. Por ejemplo, podríamos tener el siguiente archivo Car.proto:
syntax = "proto3"; message Car { required int plate_number = 1; optional string brand = 2; optional string color = 3; }
Lo que más llama la atención es el “=1”, “=2”, etc que aparece con cada campo: son los tags o etiquetas, que servirán para identificarlos cuando se utilice formato binario. Es de vital importancia que, una vez que el tipo ha sido compilado y esté utilizándose, no se modifiquen las etiquetas de los campos, ya que provocaríamos errores de parseo entre las distintas versiones del tipo.
Aparte de eso, vemos que cada entrada del mensaje consta de:
- un modificador, que puede ser required (obligatorio), optional (opcional) o repeated (puede aparecer cualquier número de veces, incluido el cero; se asemejan a los arrays dinámicos). Los campos opcionales incluyen un resultado por defecto para los casos en que no especifiquemos un valor, aunque podemos modificarlo a nuestro gusto:
optional string cad = 1 [default = “blah”];
Por último, nos fijamos en que la primera línea del archivo es syntax = «proto3». Si no utilizamos la opción syntax, el compilador dará por hecho que estamos utilizando proto2, por lo que es bastante importante especificarlo. Además, debe ser la primera línea no vacía del archivo que no sea un comentario.
4. Enumerados
Definir enumerados en un .proto es muy sencillo; solo hay que especificar el nombre de los valores que puede tomar:
enum Position { CENTER = 0; UP = 1; DOWN = 2; }
Solamente debemos tener en cuenta que la etiqueta de la primera entrada del enumerado debe ser 0, que además será la que se utilice como valor por defecto.
5. Mensajes como tipo
Podemos utilizar otros mensajes como tipo para entradas en otro mensaje. Puede estar definido en el mismo archivo, dentro del mensaje en el que lo vamos a utilizar o incluso en otro archivo. Estudiamos los tres casos:
- mensajes “hermanos”:
message A { … } message B { required A field = 1; }
message A { message B { … } } repeated B field = 1; }
message A { message B { … } required B field = 1; } message C { optional A.B val = 1; }
import "file1.proto";
6. Compilando
Una vez que ya tenemos preparado nuestro archivo example.proto, procedemos a compilarlo vía protoc:
protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/example.proto
Con la opción I, indicamos el directorio fuente (si no lo indicamos, tomará el directorio actual); con java_out estamos diciendo que queremos que se compile en Java, además de especificar el directorio destino en el que queremos que se creen los .java. Por último, se añade la ruta al archivo .proto que queremos compilar.
Como resultado, obtendremos un archivo .java con una clase por cada mensaje que hayamos definido, así como una clase Builder para crear instancias de estos mensajes.
7. Conclusiones
Esta ha sido una pequeña introducción al formato de los archivos .protoc, suficiente para empezar a probar el potencial que tiene la herramienta. En la segunda y última parte de este tutorial, ampliaremos las opciones que nos ofrece y profundizaremos un poco más en su funcionamiento.