uzumas
uzumas

Reputation: 678

Protobuf Any unmarshal

I have a proto API using Any type

message Document {
    DocumentMeta meta = 1;
    bytes data = 2;
    google.protobuf.Any details = 3;
}

On client, I have created a message named Dog and I create the details field as follows:

dog1 := events2.Dog{
    Name: "Leo",
    Id:   1,
}
var dst anypb.Any
err = anypb.MarshalFrom(&dst, &dog1, proto.MarshalOptions{})

The .pb file containing Dog proto is copied in the server also.

If I print the Document in Server, it gives correct information

Any:type_url:"type.googleapis.com/com.test.eventbus.pb.events.Dog" value:"\n\x03Leo\x10\x01"

On Server-side, I am unmarshalling without providing a specific proto.Message type(Dog)

basicDog, err := anypb.UnmarshalNew(doc.GetDetails(), proto.UnmarshalOptions{})

The UnmarshalNew fails with proto: not found

  1. I am not providing a specific type during unmarshalling since clients are allowed to send any type of message which may not be defined during application startup time.
  2. So the client generates a new proto file, generates .pb for go and copies this .go file inside the server.

How can I use .pb file on server-side while using unmarshalAny() method?

Upvotes: 0

Views: 3607

Answers (1)

Trock
Trock

Reputation: 636

Try use google.protobuf.Value

Proto file:

syntax = "proto3";

package mediation.common;

option go_package = ".;common";

import "google/protobuf/struct.proto";

message Model {
  google.protobuf.Value any = 2;
}

using:

package common

import (
    "encoding/json"
    "testing"

    "google.golang.org/protobuf/types/known/structpb"
)

type Dog struct {
    Id   int
    Name string
}

func TestAny(t *testing.T) {
    data := map[string]interface{}{
        "id":   1,
        "name": "kitty",
    }

    s, _ := structpb.NewValue(data)
    newData := s.GetStructValue()

    m := Model{Any: structpb.NewStructValue(newData)}

    var dog Dog
    unmarshal(m.GetAny(), &dog)
    t.Log(dog)

    var mm map[string]interface{}
    unmarshal(m.GetAny(), &mm)
    t.Log(mm)
}

func unmarshal(p *structpb.Value, o interface{}) error {
    byt, _ := p.MarshalJSON()
    return json.Unmarshal(byt, o)
}

Upvotes: 2

Related Questions