Skip to content

Unmarshal converts null into an empty message #55

@maratori

Description

@maratori

protoyaml.Unmarshal does not correctly handle null values in YAML for fields of message kind. Instead of setting the field to nil, it assigns an empty message.

The following test demonstrates the issue:

package bug_test

import (
	"testing"

	"buf.build/go/protoyaml"
	"github.com/stretchr/testify/require"
	"google.golang.org/genproto/googleapis/api/distribution"
)

func TestUnmarshal(t *testing.T) {
	msg := &distribution.Distribution_Exemplar{} // any proto message with a MessageKind field
	err := protoyaml.Unmarshal([]byte(`timestamp: null`), msg)
	require.NoError(t, err)
	require.Nil(t, msg.GetTimestamp()) // should pass but fails
}
=== RUN   TestUnmarshal
    unmarshal_test.go:15: 
        	Error Trace:	.../bug_test.go:15
        	Error:      	Expected nil, but got: &timestamppb.Timestamp{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(0x1400017e840)}, sizeCache:0, unknownFields:[]uint8(nil), Seconds:0, Nanos:0}
        	Test:       	TestUnmarshal
--- FAIL: TestUnmarshal (0.00s)

This issue is particularly problematic when using MarshalOptions{EmitUnpopulated: true} to generate YAML, modify it, and then unmarshal it back. Since null values do not get properly set to nil, the unmarshaled result is inconsistent with the original structure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions