I have the following protobuf setup:
import "google/protobuf/any.proto";
message EntityEnvelope {
string id = 1;
string entity_type = 2;
google.protobuf.Any entity = 3;
}
message EntityABC {
string name = 1;
}
message EntityXYZ {
string desc = 1;
}
where EntityEnvelope.entity
can be any type packed as google.protobuf.Any
. Each protobuf message is stored in the disk encoded as Base64.
When reading these messages, it works perfectly if I use the specific entity type at compile type when unpacking:
import scalapb.spark.Implicits._
spark.read.format("text")
.load("/tmp/entity").as[String]
.map { s => Base64.getDecoder.decode(s) }
.map { bytes => EntityEnvelope.parseFrom(bytes) }
.map { envelope => envelope.getEntity.unpack[EntityXYZ]}
.show()
But I want to use the same code to read any kind of entity at runtime, without having to specify its type. The "closer" I got was (but doesn't even compile):
val entityClass = Class.forName(qualifiedEntityClassNameFromRuntime)
spark.read.format("text")
.load("/tmp/entity").as[String]
.map { s => Base64.getDecoder.decode(s) }
.map { bytes => EntityEnvelope.parseFrom(bytes) }
.map { envelope => toJavaProto(envelope.getEntity).unpack(entityClass)} // ERROR: No implicits found for Encoder[Any]
.show()
Since Any
contains the typeUrl
, would be possible to find the correct descriptor and unpack it automatically at runtime, without having to specify the type at compile time?