简体   繁体   中英

Marshal/Unmarshal google.protobuf.Any proto message

I'm currently using gRPC for my API communication. Now I need the value of my request can accept any data type, be it a struct object or just a primitive data type like single integer , string , or boolean . I tried using google.protobuf.Any as below but it doesn't work when I want to marshal and unmarshal it.

message MyRequest {
    google.protobuf.Any item = 1; // could be 9, "a string", true, false, {"key": value}, etc.
}

proto-compiled result:

type MyRequest struct {
    Item *anypb.Any `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
}

I will marshal the incoming request through gRPC and save it as a JSON string in the database:

bytes, err = json.Marshal(m.request.Item)
if err != nil {
    return err
}
itemStr := string(bytes)

But when I want to unmarshal the string back into *anypb.Any by:

func getItem(itemStr string) (structpb.Value, error) {
    var item structpb.Value
    err := json.Unmarshal([]byte(itemStr), &item)
    
    if err != nil {
        return item, err
    }

    // also I've no idea on how to convert `structpb.Value` to `anypb.Any`
    return item, nil
}

It returns an error which seems to be because the struct *anypb.Any doesn't contain any of the fields in my encoded item string. Is there a correct way to solve this problem?

Consider usinganypb

In the documentation it shows an example of how to unmarshal it

m := new(foopb.MyMessage)
if err := any.UnmarshalTo(m); err != nil {
    ... // handle error
}
... // make use of m

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM