diff --git a/encoding/prototext/decode.go b/encoding/prototext/decode.go index b53805056..75289948b 100644 --- a/encoding/prototext/decode.go +++ b/encoding/prototext/decode.go @@ -31,6 +31,11 @@ func Unmarshal(b []byte, m proto.Message) error { type UnmarshalOptions struct { pragma.NoUnkeyedLiterals + // Merge merges the input into the destination message. + // The default behavior is to always reset the message before unmarshaling, + // unless Merge is specified. + Merge bool + // AllowPartial accepts input for messages that will result in missing // required fields. If AllowPartial is false (the default), Unmarshal will // return error if there are any missing required fields. @@ -62,7 +67,9 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error { // For profiling purposes, avoid changing the name of this function or // introducing other code paths for unmarshal that do not go through this. func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error { - proto.Reset(m) + if !o.Merge { + proto.Reset(m) + } if o.Resolver == nil { o.Resolver = protoregistry.GlobalTypes diff --git a/encoding/prototext/decode_test.go b/encoding/prototext/decode_test.go index 7fc90ca53..41d3c6f41 100644 --- a/encoding/prototext/decode_test.go +++ b/encoding/prototext/decode_test.go @@ -1288,6 +1288,26 @@ str_to_nested: { inputMessage: &pb2.Nests{}, inputText: "reserved_field: 'ignore this'", wantMessage: &pb2.Nests{}, + }, { + desc: "reset message when merge is not set", + inputMessage: &pb3.Scalars{ + SBool: true, + }, + inputText: `s_string: "abc"`, + wantMessage: &pb3.Scalars{ + SString: "abc", + }, + }, { + desc: "message not reset when merge is enabled", + umo: prototext.UnmarshalOptions{Merge: true}, + inputMessage: &pb3.Scalars{ + SBool: true, + }, + inputText: `s_string: "abc"`, + wantMessage: &pb3.Scalars{ + SBool: true, + SString: "abc", + }, }, { desc: "extensions of non-repeated fields", inputMessage: &pb2.Extensions{},