-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Unmarshal a value which implements JSONPBUnmarshaler #429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add a unit test for this? Thanks.
jsonpb/jsonpb.go
Outdated
@@ -673,7 +673,8 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe | |||
if targetType.Kind() == reflect.Ptr { | |||
// If input value is "null" and target is a pointer type, then the field should be treated as not set | |||
// UNLESS the target is structpb.Value, in which case it should be set to structpb.NullValue. | |||
if string(inputValue) == "null" && targetType != reflect.TypeOf(&stpb.Value{}) { | |||
_, ok := target.Interface().(JSONPBUnmarshaler) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor naming suggestion. s/ok/isJSONPBUnmarshaler/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
Curious, how do you make MyString implement JSONPBUnmarshaler? Do you hand modify the generated pb.go file or add another file under the same generated package? |
Hi, yes, we add another file under the same generated package. |
Hi, @cybrcodr , renamed "ok" to "isJSONPBUnmarshaler", and added a test. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Minor suggestions.
jsonpb/jsonpb_test.go
Outdated
@@ -789,6 +789,18 @@ func TestUnmarshalJSONPBUnmarshaler(t *testing.T) { | |||
if msg.rawJson != rawJson { | |||
t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", msg.rawJson, rawJson) | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separate this out to a different Test function to make it easier to identify. Suggest naming TestUnmarshalNullWithJSONPBUnmarshaler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
jsonpb/jsonpb_test.go
Outdated
rawJson = `{"stringField":null}` | ||
var ptrFieldMsg ptrFieldMessage | ||
if err := Unmarshal(strings.NewReader(rawJson), &ptrFieldMsg); err != nil { | ||
t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplify the error message -- "unmarshal error: %v", err
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
jsonpb/jsonpb_test.go
Outdated
if err := Unmarshal(strings.NewReader(rawJson), &ptrFieldMsg); err != nil { | ||
t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err) | ||
} | ||
if ptrFieldMsg.StringField == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be more precise to compare with expected value. Use proto.Equal to compare.
Error message can be something like "unmarshal result StringField: got %v, want %v"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
jsonpb/jsonpb_test.go
Outdated
if ptrFieldMsg.StringField == nil { | ||
t.Errorf("ptr field which implements JSONPBUnmarshaler is nil after unmarshalling with JSON {\"stringField\":null}:") | ||
} | ||
if ptrFieldMsg.StringField != nil && ptrFieldMsg.StringField.IsSet == false { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if you need the IsSet field. But if you really want to keep it, the validation here should not need to include check for StringField != nil, i.e. it should be independent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this validation, "proto.Equal" is enough, but "IsSet" is not removed, I'd like to use it to make sure func (s *stringField) UnmarshalJSONPB
is executed.
jsonpb/jsonpb_test.go
Outdated
func (s *stringField) ProtoMessage() { | ||
} | ||
|
||
func (s *stringField) MarshalJSONPB(jm *Marshaler) ([]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional. This is not necessary since the test is only on JSONPBUnmarshaler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Hi, our test cases are failed by #394 .
We defined a struct which implements interface
JSONPBUnmarshaler
, and use it as a field in another message, for example:MyString
implementsJSONPBUnmarshaler
.Before #394 , everything works fine.
After #394 , if input json is
{"name": null}
, funcUnmarshalJSONPB
onMyString
is not executed. Because it will return earlier: