Option JSON serialization/deserialization does not handle the null case correctly
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 3.4k
- Forks
- 120
- Avg merge
- 4d 17h
- Merged PRs (30d)
- 3
Description
Hi,
I believe something is wrong in the behavior of Option's UnmarshalJSON.
Say I have the very basic struct :
type Person struct {
Name string
Age mo.Option[int]
}
and a test that ensures that the person can be serialized to JSON back and forth (roundtrip) :
func TestRoundtripJSONPerson(t *testing.T) {
person := bugmooption.Person{
Name: "MyPerson",
Age: mo.None[int](),
}
serialized, err := json.Marshal(&person)
if err != nil {
t.Fatalf("Failed to serialize Person")
}
var deserialized bugmooption.Person
err := json.Unmarshal(serialized, &deserialized)
if err != nil {
t.Fatalf("Failed to deserialize Person")
}
if person != deserialized {
t.Fatalf("person should be the same before and after JSON serialization roundtrip")
}
}
The test currently fails. Indeed, after serializing, my person has a JSON field age: null.
After deserializing, I get an age which is of the form :
{
value: 0,
isPresent: true,
}
So I've had a look at the implementation. At a glance, this comment :
// if user manually set the field to be `null`, then `isPresent` should be `true` since that is want user intends the value to be
// this makes sure `isPresent` makes semantic sense, and solves the ambiguity of pointer completely
sounds very wrong to me. If the field is set to null, then I expect isPresent to be false, not true.
I'm not sure why no one else has found this behavior strange, am I missing something ?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at Option's UnmarshalJSON implementation and reproduce the roundtrip shown with a Person whose Age is None. Compare the serialized null with the deserialized Option state; done means the roundtrip preserves the absent value and the relevant JSON behavior is covered by a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100