codes: fix: marshal/unmarshal a Code to JSON fails (#2116)

Marshalling a Code to JSON and unmarshalling it failed with an
"invalid code" error message.

Code is of type uint32. It has no custom MarshalJson() implemented
therefore it is marshalled into an JSON integer value.
The UnmarshalJSON() function expected that the marshalled Code is a
String type, unmarshalling failed.

Check in UnmarshalJSON() if the value is an uint32 in the range of the
defined Code values. If it is, unmarshal it.

This commit also adds an Marshal/Unmarshal testcase.
This commit is contained in:
Fabian Holler
2018-06-01 19:56:55 +02:00
committed by Menghan Li
parent 590da37e2d
commit b94ea975f3
2 changed files with 33 additions and 0 deletions

View File

@ -22,6 +22,7 @@ package codes // import "google.golang.org/grpc/codes"
import ( import (
"fmt" "fmt"
"strconv"
) )
// A Code is an unsigned 32-bit error code as defined in the gRPC spec. // A Code is an unsigned 32-bit error code as defined in the gRPC spec.
@ -143,6 +144,8 @@ const (
// Unauthenticated indicates the request does not have valid // Unauthenticated indicates the request does not have valid
// authentication credentials for the operation. // authentication credentials for the operation.
Unauthenticated Code = 16 Unauthenticated Code = 16
_maxCode = 17
) )
var strToCode = map[string]Code{ var strToCode = map[string]Code{
@ -176,6 +179,16 @@ func (c *Code) UnmarshalJSON(b []byte) error {
if c == nil { if c == nil {
return fmt.Errorf("nil receiver passed to UnmarshalJSON") return fmt.Errorf("nil receiver passed to UnmarshalJSON")
} }
if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
if ci >= _maxCode {
return fmt.Errorf("invalid code: %q", ci)
}
*c = Code(ci)
return nil
}
if jc, ok := strToCode[string(b)]; ok { if jc, ok := strToCode[string(b)]; ok {
*c = jc *c = jc
return nil return nil

View File

@ -62,3 +62,23 @@ func TestUnmarshalJSON_UnknownInput(t *testing.T) {
} }
} }
} }
func TestUnmarshalJSON_MarshalUnmarshal(t *testing.T) {
for i := 0; i < _maxCode; i++ {
var cUnMarshaled Code
c := Code(i)
cJSON, err := json.Marshal(c)
if err != nil {
t.Errorf("marshalling %q failed: %v", c, err)
}
if err := json.Unmarshal(cJSON, &cUnMarshaled); err != nil {
t.Errorf("unmarshalling code failed: %s", err)
}
if c != cUnMarshaled {
t.Errorf("code is %q after marshalling/unmarshalling, expected %q", cUnMarshaled, c)
}
}
}