uuid icon indicating copy to clipboard operation
uuid copied to clipboard

Should uuid.Nil marshal to null instead of all zeroes

Open maroux opened this issue 2 years ago • 1 comments

The library uses the uuid.Nil value as an empty value. This suggests to me that Nil value is treated as a special value, which is in line with the RFC. However, the behavior of this value when marshaling to json is questionable. The library serializes to 00000000-0000-0000-0000-000000000000 (play) instead of null. Should this behavior be changed? Marshaling to text can probably yield an error, or just empty string, not sure.

maroux avatar Aug 04 '23 22:08 maroux

I ran into some problems while using UUID with the echo framework, which caused me a lot of inconvenience. I would be grateful if there is a solution available for this issue. Moreover, this problem results in an extra burden of validations that need to be implemented.

TestResultDTO struct {
	ConsumerId uuid.UUID `json:"consumer_id,omitempty"`
}
func (h *Handler) TestRun(c echo.Context) error {
	var testResultDTO models.TestResultDTO
	err := c.Bind(&testResultDTO)
	if err != nil {
		return err
	}
	jsonString, err := json.Marshal(testResultDTO)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(jsonString))
	return c.JSON(http.StatusCreated, testResultDTO)
}

Sending a POST request to the test endpoint:

curl --request POST \
  --url http://localhost:xxxx/test \
  --header 'Content-Type: application/json' \
  --header 'User-Agent: foo' \
  --data '{}'
{
	"consumer_id": "00000000-0000-0000-0000-000000000000"
}

Which in this case is undesirable.

I attempted the following method, but it did not properly evaluate and had issues with structures that produce new UUIDs.

TestResultDTO struct {
	ConsumerId uuid.NullUUID `json:"consumer_id,omitempty"`
}

Outcome from the same endpoint:

{
	"consumer_id": null
}

There needs to be a solution that is more compliant with other libraries. Especially when you need to perform the following in order to reduce overhead:

ProviderId         uuid.NullUUID  `json:"provider_id,omitempty" validate:"required_without=ConsumerId,uuid"`
ConsumerId      uuid.NullUUID  `json:"consumer_id,omitempty" validate:"required_without=ProviderId,uuid"`

petkostas avatar Oct 27 '23 13:10 petkostas

Following up on this, but did you ever find a solution?

Personally was expecting omitempty to result in nothing, rather than a bunch of 00000000-0000-0000-0000-000000000000s

tyliec avatar Mar 06 '24 20:03 tyliec

I'm interested in a solution for this as well.

mazar avatar Mar 25 '24 22:03 mazar

Who else would like to marshal uuid.Nil to json null? Give a 👍

Mirko607 avatar Jun 19 '24 06:06 Mirko607

What you want is uuid.NullUUID which is like a UUID but it can be null (at the cost of additional data).

uuid.Nil has a specific definition and it is not null. From RFC 4122:

[4.1.7]  Nil UUID

   The nil UUID is special form of UUID that is specified to have all
   128 bits set to zero. 

I am going to close this issue since uuid.NullUUID has the behavior you want.

pborman avatar Jun 19 '24 21:06 pborman