Open JekaNS opened 8 months ago
Encoder return empty json object "{}" In case of encoding struct that has a child as pointer with omitempty tag and this child has first field with value of zero byte (false or 0 or empty string)
Here is the test cases to reproduce:
package jsontest import ( "testing" "github.com/goccy/go-json" "github.com/stretchr/testify/assert" ) type RootInt struct { Child *ChildInt `json:"c,omitempty"` } type ChildInt struct { Value int `json:"v"` } type RootBool struct { Child *ChildBool `json:"c,omitempty"` } type ChildBool struct { Value bool `json:"v"` } type RootString struct { Child *ChildString `json:"c,omitempty"` } type ChildString struct { Value string `json:"v"` } func TestZeroFirstByteAfterPtrInt(t *testing.T) { obj := RootInt{Child: &ChildInt{Value: 0}} jsonDst, e2 := json.Marshal(obj) assert.NoError(t, e2) assert.Equal(t, `{"c":{"v":0}}`, string(jsonDst)) } func TestNonZeroFirstByteAfterPtrInt(t *testing.T) { obj := RootInt{Child: &ChildInt{Value: 1}} jsonDst, e2 := json.Marshal(obj) assert.NoError(t, e2) assert.Equal(t, `{"c":{"v":1}}`, string(jsonDst)) } func TestZeroFirstByteAfterPtrBool(t *testing.T) { obj := RootBool{Child: &ChildBool{Value: false}} jsonDst, e2 := json.Marshal(obj) assert.NoError(t, e2) assert.Equal(t, `{"c":{"v":false}}`, string(jsonDst)) } func TestNonZeroFirstByteAfterPtrBool(t *testing.T) { obj := RootBool{Child: &ChildBool{Value: true}} jsonDst, e2 := json.Marshal(obj) assert.NoError(t, e2) assert.Equal(t, `{"c":{"v":true}}`, string(jsonDst)) } func TestZeroFirstByteAfterPtrString(t *testing.T) { obj := RootString{Child: &ChildString{Value: ""}} jsonDst, e2 := json.Marshal(obj) assert.NoError(t, e2) assert.Equal(t, `{"c":{"v":""}}`, string(jsonDst)) } func TestNonZeroFirstByteAfterPtrString(t *testing.T) { obj := RootString{Child: &ChildString{Value: "a"}} jsonDst, e2 := json.Marshal(obj) assert.NoError(t, e2) assert.Equal(t, `{"c":{"v":"a"}}`, string(jsonDst)) }
Tests run result:
=== RUN TestZeroFirstByteAfterPtrInt json_bug_test.go:40: Error Trace: /Users/jeka/Veeam/workbench/projects/cast/internal/rm/casedata/json_bug_test.go:40 Error: Not equal: expected: "{\"c\":{\"v\":0}}" actual : "{}" Diff: --- Expected +++ Actual @@ -1 +1 @@ -{"c":{"v":0}} +{} Test: TestZeroFirstByteAfterPtrInt --- FAIL: TestZeroFirstByteAfterPtrInt (0.00s) Expected :{"c":{"v":0}} Actual :{} <Click to see difference> === RUN TestNonZeroFirstByteAfterPtrInt --- PASS: TestNonZeroFirstByteAfterPtrInt (0.00s) === RUN TestZeroFirstByteAfterPtrBool json_bug_test.go:58: Error Trace: /Users/jeka/Veeam/workbench/projects/cast/internal/rm/casedata/json_bug_test.go:58 Error: Not equal: expected: "{\"c\":{\"v\":false}}" actual : "{}" Diff: --- Expected +++ Actual @@ -1 +1 @@ -{"c":{"v":false}} +{} Test: TestZeroFirstByteAfterPtrBool --- FAIL: TestZeroFirstByteAfterPtrBool (0.00s) Expected :{"c":{"v":false}} Actual :{} <Click to see difference> === RUN TestNonZeroFirstByteAfterPtrBool --- PASS: TestNonZeroFirstByteAfterPtrBool (0.00s) === RUN TestZeroFirstByteAfterPtrString json_bug_test.go:76: Error Trace: /Users/jeka/Veeam/workbench/projects/cast/internal/rm/casedata/json_bug_test.go:76 Error: Not equal: expected: "{\"c\":{\"v\":\"\"}}" actual : "{}" Diff: --- Expected +++ Actual @@ -1 +1 @@ -{"c":{"v":""}} +{} Test: TestZeroFirstByteAfterPtrString --- FAIL: TestZeroFirstByteAfterPtrString (0.00s) Expected :{"c":{"v":""}} Actual :{} <Click to see difference> === RUN TestNonZeroFirstByteAfterPtrString --- PASS: TestNonZeroFirstByteAfterPtrString (0.00s) FAIL
I thik problem is here https://github.com/goccy/go-json/blob/df897aec9dc4228e585e8127b4db026d506d2b3c/internal/encoder/vm/vm.go#L585 ptrToPtr(p) in this case return not a pointer but value
Same bug with empty string. I've updated the test code and result in the first post.
Also I tried this on different architectures. Bug is reproduced on all of them:
Encoder return empty json object "{}" In case of encoding struct that has a child as pointer with omitempty tag and this child has first field with value of zero byte (false or 0 or empty string)
Here is the test cases to reproduce:
Tests run result:
I thik problem is here https://github.com/goccy/go-json/blob/df897aec9dc4228e585e8127b4db026d506d2b3c/internal/encoder/vm/vm.go#L585 ptrToPtr(p) in this case return not a pointer but value