fraibacas
fraibacas

Reputation: 23

Google Cloud Endpoints: Transcoding messages with protobuf.Any fields

I have a grpc service that takes as input a message that contains fields of type protobuf.Any and I can't figure out the way to write correct json input for it. I am running on GKE, with cloud endpoint ESP and my service running in the same pod.

The protos look like:

message AnyArray {
    repeated google.protobuf.Any value = 1;
}
message Metric {
    string metric = 1;
    int64 timestamp = 2;
    double value = 3;
    map<string, AnyArray> metadata = 4;
}

I have tried multiple combinations for the input json with no luck, most of the times cloud endpoints returns "Proto field is not repeating, cannot start list." Failed examples:

{
    "metadata": {
        "sample-key": {
            "value": [1, "one"]
        }
    },
    "metric": "request-count",
    "timestamp": 1528425789,
    "value": 0
}

{
    "metadata": {
        "sample-key": {
            "value": [{
                "@type": "type.googleapis.com/google.protobuf.Duration",
                "value": "1.212s"
            }, {
                "@type": "type.googleapis.com/google.protobuf.Duration",
                "value": "1.212s"
            }]
        }
    },
    "metric": "request-count",
    "timestamp": 1528425789,
    "value": 0
}

Response from ESP

{
    "code": 3,
    "message": "metadata[0].value: Proto field is not repeating, cannot start list.",
    "details": [{
        "@type": "type.googleapis.com/google.rpc.DebugInfo",
        "stackEntries": [],
        "detail": "internal"
    }]
}

Any help would be greatly appreciated.

Thanks!

Upvotes: 0

Views: 506

Answers (2)

fraibacas
fraibacas

Reputation: 23

Using protobuf.Struct instead of protobuf.Any solved my problem as @lizan recommended. Thanks!

Upvotes: 0

lizan
lizan

Reputation: 71

google.protobuf.Any means any proto message type so your first example doesn't work. For the second example, google.protobuf.Duration have a special JSON mapping, so following example should work:

{
    "metadata": {
        "sample-key": {
            "value": [{
                "@type": "type.googleapis.com/google.protobuf.Duration",
                "value": "1.212s"
            }, {
                "@type": "type.googleapis.com/google.protobuf.Duration",
                "value": "1.212s"
            }]
        }
    },
    "metric": "request-count",
    "timestamp": 1528425789,
    "value": 0
}

Note you will have to include all possible proto message types for the google.protobuf.Any in the proto descriptor set provided Cloud Endpoints service, otherwise it will fail to translate unknown types.

Another possible approach is use google.protobuf.Struct for your metadata, which eliminates the limitation above, but you will have to convert it to your expected types in your gRPC service.

Upvotes: 2

Related Questions