Protocol Buffers - Language Independence



Overview

Till now, we have been using Java to serialize and deserialize the Movie Theater data. However, one of the key features that Google Protocol buffers provides is "language independence". In this chapter, we will see how to serialize using Java and deserialize using Python.

Continuing with our theater example from Protocol Buffers - String chapter, following is the syntax that we need to have to instruct Protobuf that we will be creating different datatypes −

theater.proto

syntax = "proto3";
package theater;
option java_package = "com.tutorialspoint.theater";

message Theater {
   string name = 1;
   string address = 2;
  
   int32 total_capcity = 3;
   int64 mobile = 4;
   float base_ticket_price = 5;
  
   bool drive_in = 6;
   
   enum PAYMENT_SYSTEM { 
      CASH = 0;
      CREDIT_CARD = 1;
      DEBIT_CARD = 2;
      APP = 3;
   }
   PAYMENT_SYSTEM payment = 7;
   repeated string snacks = 8;
   map<string, int32> movieTicketPrice = 9;
   TheaterOwner owner = 10;
}
message TheaterOwner{
   string name = 1;
   string address = 2;
}

Serialization using Java

To use Protobuf, we will now have to use protoc binary to create the required classes from this ".proto" file. Let us see how to do that −

protoc  --java_out=. theater.proto

This will create a TheaterOuterClass.java class in com > tutorialspoint > theater folder in current directory. We're using this class in our application similar to as done in Protocol Buffers - Basic App chapter.

Using Java Classes created from Proto File

First, we will create a writer to write the theater information −

TheaterWriter.java

package com.tutorialspoint.theater;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.tutorialspoint.theater.TheaterOuterClass.Theater;
import com.tutorialspoint.theater.TheaterOuterClass.TheaterOwner;
import com.tutorialspoint.theater.TheaterOuterClass.Theater.PAYMENT_SYSTEM;

public class TheaterWriter {
   public static void main(String[] args) throws IOException {
      TheaterOwner owner = TheaterOwner.newBuilder()
         .setName("Anthony Gonsalves")
         .setAddress("513, St Paul Street, West Coast, California")
         .build();
	    
      List<String> snacks = new ArrayList<>();
      snacks.add("Popcorn");
      snacks.add("Coke");
      snacks.add("Chips");
      snacks.add("Soda");
	        
      Map<String, Integer> ticketPrice = new HashMap<>();
      ticketPrice.put("Avengers Endgame", 700);
      ticketPrice.put("Captain America", 200);
      ticketPrice.put("Wonder Woman 1984", 400);
	   
      Theater theater = Theater.newBuilder()
         .setName("Silver Screener")
         .setAddress("212, Maple Street, LA, California")
         .setDriveIn(true)
         .setTotalCapcity(320)
         .setMobile(98234567189L)
         .setBaseTicketPrice(22.45f)
         .setPayment(PAYMENT_SYSTEM.CREDIT_CARD)
         .putAllMovieTicketPrice(ticketPrice)
         .addAllSnacks(snacks)
         .setOwner(owner)
         .build();
		
      String filename = "E:/theater_protobuf_output";
      System.out.println("Saving theater information to file: " + filename);
		
      try(FileOutputStream output = new FileOutputStream(filename)){
         theater.writeTo(output);
      }
      System.out.println("Saved theater information with following data to disk: \n" + theater);
   }
}

Let us compile the project.

mvn clean install

Serialize the Java Object

Now, post compilation, let us execute the writer

> java -cp .\target\protobuf-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter

Saving theater information to file: E:/theater_protobuf_output
Saved theater information with following data to disk:
name: "Silver Screener"
address: "212, Maple Street, LA, California"
total_capcity: 320
mobile: 98234567189
base_ticket_price: 22.45
drive_in: true
payment: CREDIT_CARD
snacks: "Popcorn"
snacks: "Coke"
snacks: "Chips"
snacks: "Soda"
movieTicketPrice {
   key: "Avengers Endgame"
   value: 700
}
movieTicketPrice {
   key: "Captain America"
   value: 200
}
movieTicketPrice {
   key: "Wonder Woman 1984"
   value: 400
}
owner {
   name: "Anthony Gonsalves"
   address: "513, St Paul Street, West Coast, California"
}

Deserialize the Serialized Object Using Python

Generate Python classes from proto file

Let us generate the python code for Theater class −

protoc  --python_out=. theater.proto

Post execution of this command, you will notice an auto-generated class theater_pb2.py in current directory. This class would help us with deserialization of the Theater object.

Using Generated Python Classes

Now, let us write the reader of the data, which will read the file containing serialized object using java. −

theaterReader.py

import theater_pb2

filename = "E:/theater_protobuf_output";
print("Reading from file: " + filename)

theater = theater_pb2.Theater()

f = open(filename, "rb")
theater.ParseFromString(f.read())
f.close()

print("Read theater from disk: \n" + str(theater))

And then, let us execute the reader.

python theaterReader.py

Reading from file: E:/greeting_protobuf_output
Read theater from disk:
name: "Silver Screener"
address: "212, Maple Street, LA, California"
total_capcity: 320
mobile: 98234567189
base_ticket_price: 22.45
drive_in: true
payment: CREDIT_CARD
snacks: "Popcorn"
snacks: "Coke"
snacks: "Chips"
snacks: "Soda"
movieTicketPrice {
  key: "Wonder Woman 1984"
  value: 400
}
movieTicketPrice {
  key: "Captain America"
  value: 200
}
movieTicketPrice {
  key: "Avengers Endgame"
  value: 700
}
owner {
  name: "Anthony Gonsalves"
  address: "513, St Paul Street, West Coast, California"
}

So, as we see, all the values which were written by the Java client were correctly deserialized and read by our Python client which effectively means Protobuf is language independent.

Advertisements