Single level Protobuf Struct fields can be parsed to Python dicts by passing the Struct to the Python dict. However, this does not work with nested dicts. Is there an officially supported method to convert nested Protobuf structs to dicts?
from google.protobuf.struct_pb2 import Struct
simple_struct = Struct()
simple_struct.update({"hi": 1, "there": 2})
print(dict(simple_struct))
nested_struct = Struct()
nested_struct.update({"hi": 1, "over": {"there": 23}})
print(dict(nested_struct))
# Output
{'there': 2.0, 'hi': 1.0}
{'hi': 1.0, 'over': fields {
key: "there"
value {
number_value: 23.0
}
}
}
I could not find any supported method, but it is possible to recursively parse Protobuf Structs and return a proper Python dict that way.
from typing import Dict, List, Union
from google.protobuf.struct_pb2 import Struct, ListValue, Value
def struct_to_dict(value: Union[Struct, ListValue, Value, None, str, float, bool]) -> Union[None, str, float, bool, Dict, List]:
if isinstance(value, ListValue):
return [struct_to_dict(v) for v in value.values]
if isinstance(value, Struct):
return {k: struct_to_dict(v) for k, v in value.items()}
if isinstance(value, Value):
which_oneof = value.WhichOneof('kind')
if not which_oneof or which_oneof == 'null_value':
return None
return struct_to_dict(getattr(value, which_oneof))
return value
struct = Struct()
struct.update({"hi": 1, "over": [23, 45, None, 6.7, "there", [8.9, "10"], {"key": None}]})
out = struct_to_dict(struct)
print("bad:")
print(dict(struct))
print("good:")
print(out)
# Output
bad:
{'hi': 1.0, 'over': values {
number_value: 23
}
values {
number_value: 45
}
values {
null_value: NULL_VALUE
}
values {
number_value: 6.7
}
values {
string_value: "there"
}
values {
list_value {
values {
number_value: 8.9
}
values {
string_value: "10"
}
}
}
values {
struct_value {
fields {
key: "key"
value {
null_value: NULL_VALUE
}
}
}
}
}
good:
{'hi': 1.0, 'over': [23.0, 45.0, None, 6.7, 'there', [8.9, '10'], {'key': None}]}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With