Can you represent an object that can have arbitrary fields in proto3? - protocol-buffers

Consider the following json representation of an object
{
"format": "0.0.1",
"has_impl": true,
"mtv_1b": 1,
"mtv_1c": "h",
"ktc_12": true,
"ktc_zz": true,
}
The first two format and has_impl fields are known. In addition, the object may have arbitrary number of mtv_XX and ktc_XX like fields.
Is such an object representable in proto3 and how would you go at it ?
The following could be an obvious starting point. Are there a combination of oneOf, WellKnownTypes that could be used here ?
message MyObject {
string format = 0;
bool has_impl = 1;
// Is there anything that can go in here ?
....
}

Not directly. The closest you can do would be to have a Struct (which is a map<string, Value>, where Value is a oneof over common types), using struct.proto. Not quite the same, but allows the same ideas.

Related

How to check the type of a variable in ESQL

I would like to check if a variable is a Char or Decimal. In Java, I would write the following. How would I do it in ESQL?
if (s instanceof String) {
// s is String
} else if (s instanceof Integer) {
// s is Integer value
}
As far as I know it is not possible in ESQL.
There is a FIELDTYPE function, but it does not give you the data type.
When programming in IIB you generally use the parsers to produce the message tree with fields in the correct data type, see for example XMLNSC data types when you work with XML messages. There was a similiar discussion here.

How to read arbitrary object from arangodb using cursor.ReadDocument()

I am trying to build a fairly generalizable service to create graphs in arangodb.
In my ReadVertex() function, I would like to be able to read a property with arbitrary fields of a vertex and read it into a variable, preferably a string without having to create a specific struct with the json tags hardcoded for particular properties.
I have no problem inserting arbitrary objects as a property of a vertex, and I've tried reading them into a string, but it always comes up blank.
An example of what I would like to accomplish: if a vertex has a property: "Prop1": {"Nested1": true, "Nested2": false}, and a property "Prop2": "Just a string", in my ReadVertex() function I would like to be able to do something along the lines of
// query the database and get a cursor containing prop1 and prop2
var prop1 someType
cursor.ReadDocument(ctx, &prop1)
fmt.Println(prop1.String()) // should print {"Prop1": {"Nested1": true, "Nested2": false}}
var prop2 someType
cursor.ReadDocument(ctx, &prop2)
fmt.Println(prop2.String()) // should print {"Prop2": "Just a string"}
And I would like this to work having prop1 and prop2 be of the same type.
So it turns out the answer was a lot more simple than I thought it would be. This works if prop1 and prop2 are type interface{}, it reads the data in as a map, then as long as the keys in the map are all strings (which they are in my case), to turn it into a json string I can just use json.Marshal() and cast the returned byte array as a string.

Is a map backwards compatible with a repeated keyvaluepair?

Am I able to use
message Foo {
map<string, string> foo = 1;
}
in place of
message Foo {
repeated KeyValuePair foo = 1;
}
message KeyValuePair {
string key = 1;
string value = 2;
}
?
The first source is in proto3 and the second is in proto2.
As long as you don't have duplicate keys, they will be very similar. If you have duplicate keys, using a map will have different behaviour, as duplicatws will either cause overwrites or an exception (I can't recall which, sorry). Also, "repeated" is usually implemented as a list/array/etc, so: order is retained. "map" is usually implemented with some kind of map/dictionary structure, where order is not usually guaranteed.
So: if order doesn't matter and you always have unique keys: you're fine.

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.)

How to ask protoc to use a value instead of a pointer as the value side of a map with Go?

I am using protocol buffers defined like this:
message Index {
message albums {
repeated string name = 1;
}
map<string, albums> artists_albums= 1;
map<int32, albums> year_albums = 2;
}
It generates go code like this:
type Index struct {
ArtistsAlbums map[string]*IndexAlbums
YearAlbums map[int32]*IndexAlbums
}
How can I make it generate map values of type IndexAlbums instead of *IndexAlbums?
If you use gogoprotobuf then there is an extension that will allow that
map<string, albums> artists_albums = 1 [(gogoproto.nullable) = false];
With regular goprotobuf I don't believe there is a way.
nullable, if false, a field is generated without a pointer (see warning below).
Warning about nullable: According to the Protocol
Buffer specification, you should be able to tell whether a field is
set or unset. With the option nullable=false this feature is lost,
since your non-nullable fields will always be set. It can be seen as a
layer on top of Protocol Buffers, where before and after marshalling
all non-nullable fields are set and they cannot be unset.

Resources