Protobuf: help with oneof

Created on 27 Jul 2016  路  7Comments  路  Source: golang/protobuf

I have googling but i not find a answer How can populate proto with oneof of messages

we have

message TelemetryEvent {
string version = 6;
oneof event_type {
Alarm alarm = 8;
Data data = 9;

message Alarm {
string cod = 1;
}
}
....

a := &telemetry_service_proto.TelemetryEvent_Alarm{}
t := &telemetry_service_proto.TelemetryEvent{}
a.Cod = "adf"
t.EventId = "112"
t.EventType = a

cannot use a (type *telemetry_service_proto.TelemetryEvent_Alarm) as type telemetry_service_proto.isTelemetryEvent_EventType in assignment:
*telemetry_service_proto.TelemetryEvent_Alarm does not implement telemetry_service_proto.isTelemetryEvent_EventType (missing telemetry_service_proto.isTelemetryEvent

Many thanks and i hope this example can help to other

question

Most helpful comment

This is the correct (but clunky) way:

test := &pb.TelemetryEvent{
    EventId:      "adfadk9e-dfedda",
    EventDtLocal: 125412544,
    EventType: &pb.TelemetryEvent_Alarm_{
        &pb.TelemetryEvent_Alarm{
            Cod: "b",
        },
    },
}

All 7 comments

From the package doc, given a file test.proto:

package example;

enum FOO { X = 17; }

message Test {
  required string label = 1;
  optional int32 type = 2 [default=77];
  repeated int64 reps = 3;
  optional group OptionalGroup = 4 {
    required string RequiredField = 5;
  }
  oneof union {
    int32 number = 6;
    string name = 7;
  }
}

you can set a oneof like this:

package main

import pb "./example.pb"

func main() {
    test := &pb.Test{
        // ... snip ...
        Union: &pb.Test_Name{"fred"},
    }
    // ... snip ...
    // Use a type switch to determine which oneof was set.
    switch u := test.Union.(type) {
    case *pb.Test_Number: // u.Number contains the number.
    case *pb.Test_Name: // u.Name contains the string.
    }
}

the issue is in my example the oneof is other message not a primitive type and I thinks this is the dificulty.

following my example I have tried

test := &pb.TelemetryEvent{
        EventId:      "adfadk9e-dfedda",
        EventDtLocal: 125412544,
        EventType: &pb.TelemetryEvent_Alarm{
            Cod: "b",
        },
    }

Found it: the value you must use for the oneof is called TelemetryEvent_Alarm_ (notice the trailing underscore). You can see for yourself by examining the generated code. The reason is not because it's a primitive, but because you have a nested type that collides with the oneof field name.

other this must be wrong

case 1

test := &pb.TelemetryEvent{
        EventId:      "adfadk9e-dfedda",
        EventDtLocal: 125412544,
        EventType: &pb.TelemetryEvent_Alarm{
            Cod: "b",
        },
    }

the error is: 

./app.go:42: cannot use telemetry_service_proto.TelemetryEvent_Alarm literal (type *telemetry_service_proto.TelemetryEvent_Alarm) as type telemetry_service_proto.isTelemetryEvent_EventType in field value:
    *telemetry_service_proto.TelemetryEvent_Alarm does not implement telemetry_service_proto.isTelemetryEvent_EventType (missing telemetry_service_proto.isTelemetryEvent_EventType method)

case 2 using with _

test := &pb.TelemetryEvent{
        EventId:      "adfadk9e-dfedda",
        EventDtLocal: 125412544,
        EventType: &pb.TelemetryEvent_Alarm_{
            Cod: "b",
        },
    }

./app.go:41: unknown telemetry_service_proto.TelemetryEvent_Alarm_ field 'Cod' in struct literal

thanks for your time to review

This is the correct (but clunky) way:

test := &pb.TelemetryEvent{
    EventId:      "adfadk9e-dfedda",
    EventDtLocal: 125412544,
    EventType: &pb.TelemetryEvent_Alarm_{
        &pb.TelemetryEvent_Alarm{
            Cod: "b",
        },
    },
}

wow, it works perfect thank you very much. I hope this thread help to other user how is right away to build oneof messages

well done

what about in java? thx.

Was this page helpful?
0 / 5 - 0 ratings