Reputation: 179
Suppose you have this protobuf model:
message ComplexKey {
string name = 1;
int32 domainId = 2;
}
message KeyMsg {
oneof KeyMsgOneOf {
string name = 1;
ComplexKey complexName= 2;
}
}
and an object obj, that you know is either a string or a ComplexKey.
Question
Whitout explicitly checking the obj class type, which is the most efficient way to build a new KeyMsg instance with the obj placed in the correct field using the protobuf Java API?
UPDATE: it would be great if protoc generates an helper method to do what I need.
UPDATE2: given the correct comment from Mark G. below and supposing that all fields differ in type, the best solution I've find so far is (simplified version):
List<FieldDescriptor> lfd = oneOfFieldDescriptor.getFields();
for (FieldDescriptor fieldDescriptor : lfd) {
if (fieldDescriptor.getDefaultValue().getClass() == oVal.getClass()) {
vmVal = ValueMsg.newBuilder().setField(fieldDescriptor, oVal).build();
break;
}
}
Upvotes: 11
Views: 15718
Reputation: 1888
You can use switch-case:
public Object demo() {
KeyMsg keyMsg = KeyMsg.newBuilder().build();
final KeyMsg.KeyMsgOneOfCase oneOfCase = keyMsg.getKeyMsgOneOfCase();
switch (oneOfCase) {
case NAME: return keyMsg.getName();
case COMPLEX_NAME: return keyMsg.getComplexName();
case KEY_MSG_ONE_OF_NOT_SET: return null;
}
}
Upvotes: 8
Reputation: 140299
I doubt there is a better way than using instanceof
:
KeyMsg.Builder builder = KeyMsg.newBuilder();
if (obj instanceof String) {
builder.setName((String) obj);
} else if (obj instanceof ComplexKey) {
builder.setComplexName((ComplexKey) obj);
} else {
throw new AssertionError("Not a String or ComplexKey");
}
KeyMsg msg = builder.build();
Upvotes: 1