Title: Unpack a protobuf string to Any value map in Ruby
Tags: ruby;protocol-buffers
Question: A service I am interacting with has a grpc endpoint that returns response similar to following:
&quot;transactions&quot;: [
&quot;transactionIdentifier&quot;: {
&quot;id&quot;: &quot;xyz&quot;
},
&quot;operations&quot;: [
{
&quot;operationIdentifier&quot;: {

},
&quot;type&quot;: &quot;sometype&quot;,
&quot;status&quot;: &quot;Success&quot;,
&quot;metadata&quot;: {
&quot;0&quot;: {
&quot;@type&quot;: &quot;type.googleapis.com/google.protobuf.Value&quot;,
&quot;value&quot;: {
&quot;AccountId&quot;: &quot;5HpLdCTNBQDjFomqpG2XWadgB4zHTuqQqNHhUyYbett7k1RR&quot;
}
},
&quot;1&quot;: {
&quot;@type&quot;: &quot;type.googleapis.com/google.protobuf.Value&quot;,
&quot;value&quot;: {
&quot;u128&quot;: 16100001494
}
}
}
},
]
In my Ruby code, I am trying to parse out the metadata attribute into a string -&gt; object map. This attribute is defined in the proto file as:
syntax = &quot;proto3&quot;;
// Metadata stores any operations specific info
map<string, google.protobuf.Any&gt; metadata = 8;
I am struggling to figure out how to unpack this metadata into a reasonable map in Ruby. My best result so far:
&gt; m1 = metadata[&quot;0&quot;]
=&gt; <Googl75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Protobu75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Any: type_url: &quot;type.googleapis.com/google.protobuf.Value&quot;, value: &quot;*A
AccountId205HpLdCTNBQDjFomqpG2XWadgB4zHTuqQqNHhUyYbett7k1RR&quot;&gt;
&gt;  m1.unpack(String)
NoMethodError: undefined method `descriptor' for String:Class
from /Users/someuser/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/google-protobuf-3.17.3-universal-darwin/lib/google/protobuf/well_known_types.rb:70:in `is'
&gt; m1.unpack(Googl75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Protobu75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Value)
&gt; <Googl75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Protobu75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Value: struct_value: <Googl75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Protobu75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Struct: fields: {&quot;AccountId&quot;=&gt;<Googl75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Protobu75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Value: string_value: &quot;5HpLdCTNBQDjFomqpG2XWadgB4zHTuqQqNHhUyYbett7k1RR&quot;&gt;}&gt;&gt;
&gt; m1.unpack(Googl75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Protobu75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Value).to_ruby
=&gt; <Googl75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Protobu75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Struct: fields: {&quot;AccountId&quot;=&gt;<Googl75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Protobu75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Value: string_value: &quot;5HpLdCTNBQDjFomqpG2XWadgB4zHTuqQqNHhUyYbett7k1RR&quot;&gt;}&gt;
&gt; m1.unpack(Googl75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Protobu75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0Value).to_ruby.fields[&quot;AccountId&quot;].to_ruby
=&gt; &quot;5HpLdCTNBQDjFomqpG2XWadgB4zHTuqQqNHhUyYbett7k1RR&quot;
Is there an elegant way to do convert this metadata into a string-&gt;object map?



{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 0, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2021:00:12/01/21', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<ruby><protocol-buffers>', 'Title': 'Unpack a protobuf string to Any value map in Ruby', 'ViewCount': 207, 'id': 70192531, 'user_AboutMe': '', 'user_AccountId': 1396142.0, 'user_DisplayName': 'septerr', 'user_Reputation': 6315.0, 'user_Views': 264.0, 'user_id': 1325849.0}}