Skip to content

Instantly share code, notes, and snippets.

@johnllao
Created November 5, 2015 04:25
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnllao/5ffbe24a021891e7d887 to your computer and use it in GitHub Desktop.
Save johnllao/5ffbe24a021891e7d887 to your computer and use it in GitHub Desktop.
Protobuf Descriptor and Dynamic Messages
package org.hello.protobuf;
import java.util.Map;
import com.google.protobuf.*;
import com.google.protobuf.Descriptors.*;
import com.google.protobuf.DescriptorProtos.*;
public class HelloProto {
public static void main(String[] args) throws Exception {
final String descFile = "proto/proto.desc";
final String proto = "Model.proto";
final String messageTypeName = "Member";
Map<String, FileDescriptorProto> fileDescProtos = ProtoUtil.getFileDescriptorProtos(descFile);
FileDescriptorProto fileDescProto = fileDescProtos.get(proto);
FileDescriptor[] dependencies = ProtoUtil.getDependencies(fileDescProtos, fileDescProto);
FileDescriptor fileDesc = FileDescriptor.buildFrom(fileDescProto, dependencies);
Descriptor desc = fileDesc.findMessageTypeByName(messageTypeName);
displayFieldDetails(desc.findFieldByName("id"));
displayFieldDetails(desc.findFieldByName("name"));
displayFieldDetails(desc.findFieldByName("address"));
displayFieldDetails(desc.findFieldByName("country"));
displayFieldDetails(desc.findFieldByName("city"));
displayFieldDetails(desc.findFieldByName("gender"));
System.out.println();
DynamicMessage dynMessage = DynamicMessage.newBuilder(desc)
.setField(desc.findFieldByName("id"), 1)
.setField(desc.findFieldByName("name"), "John Lao")
.setField(desc.findFieldByName("address"), "Block 1 Happy St.")
.setField(desc.findFieldByName("country"), createCountryCity(desc.findFieldByName("country").getMessageType()))
.setField(desc.findFieldByName("city"), createCountryCity(desc.findFieldByName("city").getMessageType()))
.setField(desc.findFieldByName("gender"), desc.findFieldByName("gender").getEnumType().findValueByName("MALE"))
.build();
byte[] dynMessageInBytes = dynMessage.toByteArray();
DynamicMessage dynMessage2 = DynamicMessage.parseFrom(desc, dynMessageInBytes);
System.out.println(dynMessage2);
}
private static DynamicMessage createCountryCity(Descriptor desc) {
DynamicMessage dynMessage = DynamicMessage.newBuilder(desc)
.setField(desc.findFieldByName("code"), "SG")
.setField(desc.findFieldByName("name"), "Singapore")
.build();
return dynMessage;
}
private static void displayFieldDetails(FieldDescriptor fieldDesc) {
System.out.printf("%s : %s",
fieldDesc.getName(),
fieldDesc.getJavaType().name());
if (fieldDesc.getJavaType().name().equals("MESSAGE")) {
System.out.printf(" (%s)", fieldDesc.getMessageType().getName());
}
else if (fieldDesc.getJavaType().name().equals("ENUM")) {
System.out.printf(" (%s)", fieldDesc.getEnumType().getName());
}
System.out.println();
}
}
package org.hello.proto;
import "Static.proto";
message Member {
required int32 id = 1;
required string name = 2;
required string address = 3;
required Country country = 4;
required City city = 5;
required Gender gender = 6;
}
@echo off
erase /F /Q proto\proto.desc
protoc.exe --include_imports --proto_path=proto --descriptor_set_out=proto/proto.desc proto/*
@echo on
package org.hello.protobuf;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.protobuf.*;
import com.google.protobuf.DescriptorProtos.*;
import com.google.protobuf.Descriptors.*;
public class ProtoUtil {
public static FileDescriptorSet getFileDescriptorSet(String descFilePath) throws Exception {
InputStream inStream = HelloProto.class.getClassLoader().getResourceAsStream(descFilePath);
FileDescriptorSet fileDescSet = FileDescriptorSet.parseFrom(inStream);
return fileDescSet;
}
public static Map<String, FileDescriptorProto> getFileDescriptorProtos(String descFilePath) throws Exception {
FileDescriptorSet fileDescSet = getFileDescriptorSet(descFilePath);
return getFileDescriptorProtos(fileDescSet);
}
public static Map<String, FileDescriptorProto> getFileDescriptorProtos(FileDescriptorSet fileDescSet) {
Map<String, FileDescriptorProto> map = new HashMap<String, FileDescriptorProto>();
List<FileDescriptorProto> fileDescProtos = fileDescSet.getFileList();
for (FileDescriptorProto fileDescProto : fileDescProtos) {
map.put(fileDescProto.getName(), fileDescProto);
}
return map;
}
public static FileDescriptor[] getDependencies(Map<String, FileDescriptorProto> fileDescProtos, FileDescriptorProto fileDescProto) throws Exception {
if (fileDescProto.getDependencyCount() == 0)
return new FileDescriptor[0];
ProtocolStringList dependencyList = fileDescProto.getDependencyList();
String[] dependencyArray = dependencyList.toArray(new String[0]);
int noOfDependencies = dependencyList.size();
FileDescriptor[] dependencies = new FileDescriptor[noOfDependencies];
for (int i = 0; i < noOfDependencies; i++) {
FileDescriptorProto dependencyFileDescProto = fileDescProtos.get(dependencyArray[i]);
FileDescriptor dependencyFileDesc = FileDescriptor.buildFrom(dependencyFileDescProto, getDependencies(fileDescProtos, dependencyFileDescProto));
dependencies[i] = dependencyFileDesc;
}
return dependencies;
}
}
package org.hello.proto;
message Country {
required string code = 1;
required string name = 2;
}
message City {
required string code = 1;
required string name = 2;
}
enum Gender {
MALE = 0;
FEMALE = 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment