diff --git a/codec.go b/codec.go index bc0fe989..fab38f0c 100644 --- a/codec.go +++ b/codec.go @@ -144,7 +144,9 @@ func (c *protoJSONCodec) Unmarshal(binary []byte, message any) error { if len(binary) == 0 { return errors.New("zero-length payload is not a valid JSON object") } - var options protojson.UnmarshalOptions + // Discard unknown fields so clients and servers aren't forced to always use + // exactly the same version of the schema. + options := protojson.UnmarshalOptions{DiscardUnknown: true} return options.Unmarshal(binary, protoMessage) } diff --git a/codec_test.go b/codec_test.go index b27e2562..56f78bf3 100644 --- a/codec_test.go +++ b/codec_test.go @@ -100,13 +100,28 @@ func TestStableCodec(t *testing.T) { func TestJSONCodec(t *testing.T) { t.Parallel() - var empty emptypb.Empty codec := &protoJSONCodec{name: "json"} - err := codec.Unmarshal([]byte{}, &empty) - assert.NotNil(t, err) - assert.True( - t, - strings.Contains(err.Error(), "valid JSON"), - assert.Sprintf(`error message should explain that "" is not a valid JSON object`), - ) + + t.Run("success", func(t *testing.T) { + t.Parallel() + err := codec.Unmarshal([]byte("{}"), &emptypb.Empty{}) + assert.Nil(t, err) + }) + + t.Run("unknown fields", func(t *testing.T) { + t.Parallel() + err := codec.Unmarshal([]byte(`{"foo": "bar"}`), &emptypb.Empty{}) + assert.Nil(t, err) + }) + + t.Run("empty string", func(t *testing.T) { + t.Parallel() + err := codec.Unmarshal([]byte{}, &emptypb.Empty{}) + assert.NotNil(t, err) + assert.True( + t, + strings.Contains(err.Error(), "valid JSON"), + assert.Sprintf(`error message should explain that "" is not a valid JSON object`), + ) + }) }