How to declare arrays properly in google protobuf - protocol-buffers

Here is how I have defined a message:
message PhoneNumberAndTypes {
repeated Type types = 1;
Phone number = 2;
}
And when I added the types using .addTypes() and printed the object in console, it came out like below:
phone_numbers {
types: HOME
types: MOBILE
phone_number {
number: "9912300000"
}
}
But I hoped for the types to be like [HOME,MOBILE].
What change should I make?

Actually its a List inside while I debugged it. The "printing" on console did not necessarily reflect the actual object properties.
[HOME, MOBILE]

Related

Different message types with the same unique ID in protobuf

I'm trying to reverse-engineer and document several protobufs for which I don't have the descriptor metadata, and to create .proto files for them. It's been going great until I encountered a protobuf where two completely differently structured messages share the same unique ID. The top level is simple:
message main
{
string user=1;
repeated Section sections=2;
}
Looking at the Section type, there are some that look like this:
message Section
{
string name=1;
string fulldescription=2;
string briefdescription=3;
int32 level=4;
...
}
...and some that look like this:
message Section
{
int32 cost=1;
int32 tier=2;
int64 timestamp=3;
...
}
It would make perfect sense if one of these had the id of 2 and the other of, say, 3, but no, both types show with the unique ID of 2. The protobuf documentation very clearly states that each field in the message definition must have a unique number, and here is a perfectly valid (well, working) protobuf that does the exact opposite. I don't understand how it's possible or, more importantly, how to re-create this in the .proto file?
This does not seem to be a "oneof" situation either, since both message types are present in the same protobuf at the same time, and at any rate the "oneof" alternatives would still have different identifiers for fields of different types.
For reference, here's an example excerpt from the output generated by protoc --decode-raw, which I'm trying to document:
1 {
1: "User123"
2 {
1 {
1: "JohnDoe"
2: "This is the full description of the user, with a lot of details"
3: "A brief summary of the above"
4: 13
}
}
2 {
1 {
1: 135
2: 2
3: 1653606400
}
}
}
(This post seems to be asking the same thing, but it's old and doesn't have an actual answer: Can you assign multiple different value types to one field in a repeated Protobuf message?)
(This is my absolutely very first StackOverflow question, so apologies if the quality of the post is not up to snuff; please let me know what I need to add to make it clearer).

Defining a set of pre-populated protobuf messages?

I want to be able to supply a pre-instantiated message by name rather than populating it from scratch. For example, given the following schema:
message Animal {
required int32 num_legs = 1;
required int32 num_eyes = 2;
}
message Zoo {
repeated Animal animals;
}
I want to be able quickly to define a Zoo in my config file by choosing from a set of known animals:
// config.json
zoo: {
animals: [snake, bird]
}
where snake and bird are already defined:
// animals.json
bird: {
num_legs: 2
num_eyes: 2
}
snake: {
num_legs: 0
num_eyes: 2
}
What's the most elegant way to do this?
The protobuf API has methods to convert protobuf⬌JSON. For C++ you can use util::JsonStringToMessage, other languages have their API versions too (you didn't specify a language). Wrap this in a simple helper function and use your language's multi-line string constant syntax to embed the message in JSON format directly into your source.
To get your named predefined messages, use a language that has string interpolation. (Not native to C++, unfortunately, but here is a SO answer talking about ways you might do it.)

Protobuf message / enum type rename and wire compatibility?

Is it (practically) possible to change the type name of a protobuf message type (or enum) without breaking communications?
Obviously the using code would need to be adpated to re-compile. The question is if old clients that use the same structure, but the old names, would continue to work?
Example, base on the real file:
test.proto:
syntax = "proto3";
package test;
// ...
message TestMsgA {
message TestMsgB { // should be called TestMsgZZZ going forward
// ...
enum TestMsgBEnum { // should be called TestMsgZZZEnum going forward
// ...
}
TestMsgBEnum foo = 1;
// ...
}
repeated TestMsgB bar = 1;
// ...
}
Does the on-the-wire format of the protobuf payload change in any way if type or enum names are changed?
If you're talking about the binary format, then no: names don't matter and will not impact your ability to load data; For enums, only the integer value is stored in the payload. For fields, only the field-number is stored.
Obviously if you swap two names, confusion could happen, but: it should load as long as the structure matches.
If you're talking about the JSON format, then it may matter.

How to add default values to input arguments in graphql

I have this input type and I would like to add a default Value to one of the fields. I want to add 0 to the value field inside the ExampleInput.
type ExampleType {
value: Int
another: String
}
type Mutation {
example(input: ExampleInput): ExampleType
}
input ExampleInput {
value: Int
another: String
}
Any ideas?
It looks like the grammar allows default values on input object types, so you can declare
input ExampleInput {
value: Int = 0
another: String
isAvailable: Boolean = false
}
The spec is clear that default values exist and explains how they get used (first bullet under "Input Coercion").
(Whether any specific tooling supports this is probably variable: graphql.org had an informal version of the IDL for quite a while before it was actually in the spec, and I have the impression some libraries haven't caught up to the released spec yet.)

Using protobuf enum value as a field number

I'm wondering if it is possible to use Google Protocol Buffers' enum constants as a field number of other messages, like
enum Code {
FOO = 100;
BAR = 101;
}
message Message {
required string foo = FOO;
}
This code doesn't work because FOO's type is enum Code and only a number can be used as a field number.
I am trying to build polymorphic message definitions like this animal example, that defines Cat = 1; in enum Type and required Cat animal = 100; as a unique extension number.
I thought it'd be nice to do
message Message {
required string foo = FOO.value;
}
, so that I can ensure the uniqueness of the extension field number without introducing another magic number.
So the question: is it possible to refer an enum's integer value in the protocol buffer language?
No, there is no way to do this. Sorry.
BTW, two enumerants of the same enum type can actually have the same numeric value, so defining these values in an enum does not actually ensure uniqueness.

Resources