6

I have a ProtoBuf object. I'd like to detect when a particular field is using the default, versus explicitly supplied.

message vector_measurement
{
    measurement x = 1;
    measurement y = 2;
    measurement z = 3;
}
...
message measurement
{
    ...
    float value = 2;
    ...
}

When I use HasField it returns True, yet this is clearly not the case:

c = my_vector

print(c)
# x {
#   value: 60.3813476562
# }
# y {
#   value: 0.444311201572
# }
# z {
# }

print(c.x)
# value: 60.3813476562

print(c.z)
#

print(c.z==None)
# False

print(c.z.value)
# 0

print( c.HasField('x'), c.HasField('z') )
# (True, True )

print (c.z.HasField('value') )
# ValueError: Protocol message has no non-repeated submessage field "value"

The string representation seems to know that z is using a default value; how can I detect this myself?

Phrogz
  • 296,393
  • 112
  • 651
  • 745

1 Answers1

7

You can check if a message is the default by calling ByteSize() on the message:

print(c.x.ByteSize())
# 5

print(c.z.ByteSize())
# 0

However, note that this is true for every default value, not just those not sent with the message. In other words, if each component value is explicitly set to exactly match the default, it will then report ByteSize()==0:

print(c.x, c.x.ByteSize())
#myBool: true
#stdDev: 1.06
#value: 14.32
# 12

c.x.myBool = False
print(c.x, c.x.ByteSize())
#stdDev: 1.06
#value: 14.32
# 10

c.x.value = 0
print(c.x, c.x.ByteSize())
#stdDev: 1.06
# 5

c.x.stdDev = 0
print(c.x, c.x.ByteSize())
# 0

There is no difference in ProtoBuf3 between an empty message and a message that has default values.

Phrogz
  • 296,393
  • 112
  • 651
  • 745