Protobuf: jsonpb not able to unmarshal when enum marshalled as string

Created on 2 Aug 2017  路  8Comments  路  Source: golang/protobuf

I use jsonpb to marshal the protobuf object to json string. Use EnumsAsInts: false so that the enum field is written as a string in json.
But when I use jsonpb to unmarshall it back to protobuf i am getting the following error:
Received unexpected error "unknown value \"ERROR\" for enum logging.LogLevel"

But when I set EnumsAsInts: true and the enum is written as a int, the unmarshal works.
The unmarshal should also be able to unmarshal enum from string, right?

Most helpful comment

try to use package "github.com/golang/protobuf/jsonpb" not gogo version

All 8 comments

Hmm... the following testcases show that it can unmarshal string to enum value --
https://github.com/golang/protobuf/blob/master/jsonpb/jsonpb_test.go#L507:L511

Can you provide the proto definition and the JSON string input? Simplifying it only to the error case would be good.

Thanks.

@cybrcodr
Here is my protobuf definition

enum LogLevel {
    FATAL = 0;
    ERROR = 1;
    WARN = 2;
    INFO = 3;
}
message ServiceLog {
    LogLevel level = 1;
    string message = 2;
}

And here is my testing code:

import (
    "testing"
    "github.com/golang/protobuf/jsonpb"
    "github.com/stretchr/testify/assert"
    "strings"
)

func TestUnmarshal(t *testing.T) {
    logJson := `{"level":"ERROR","message":"hello world"}`
    um := jsonpb.Unmarshaler{}
    log2 := ServiceLog{}
    err := um.Unmarshal(strings.NewReader(logJson), &log2)
    assert.NoError(t, err)
}

I tried the protobuf unit-test and I can successfully run it. But not sure why my own tests are failing though.

Sorry for the false alarm. I think I vendored a older version of protobuf that caused this. Feel free to close this

Sorry for the late response. No worries. I tried it out just to verify and your case works for me.

    log2 := ServiceLog{}
    err := um.Unmarshal(strings.NewReader(logJson), &log2)
    log2 := &ServiceLog{}
    err := um.Unmarshal(strings.NewReader(logJson), log2)

Hi, I checked on 2 cases. First code is that @guodongx mentioned, Second code is just that I checked with pointer.
2 cases result are different.
First case is showing LogLevel by "FATAL" for default.
but second case is losing default value and not include LogLevel parameter.
In the real development, we are using pointer for return value. So I am losing default enum values.
What is the solution? or is this Protobuf bug?

my workaround: register manullay if protobuf shall not be initialized at proper phase

func init() {
  proto.RegisterEnum("MY_ENUM, MY_ENUM_name, MY_ENUM_value)
}

try to use package "github.com/golang/protobuf/jsonpb" not gogo version

Was this page helpful?
0 / 5 - 0 ratings

Related issues

seungryulchoisc picture seungryulchoisc  路  3Comments

abhishekvaid picture abhishekvaid  路  4Comments

junghoahnsc picture junghoahnsc  路  5Comments

occho picture occho  路  5Comments

leduy99 picture leduy99  路  4Comments