Skip to content

Commit c463aa1

Browse files
authored
Merge pull request #173 from toffaletti/more-nil-interface-fixes
More nil interface fixes
2 parents 9277257 + b5d2607 commit c463aa1

File tree

4 files changed

+92
-16
lines changed

4 files changed

+92
-16
lines changed

feature_reflect_native.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,15 +391,20 @@ func (codec *nonEmptyInterfaceCodec) Decode(ptr unsafe.Pointer, iter *Iterator)
391391
e.typ = nonEmptyInterface.itab.typ
392392
e.word = nonEmptyInterface.word
393393
iter.ReadVal(&i)
394+
if e.word == nil {
395+
nonEmptyInterface.itab = nil
396+
}
394397
nonEmptyInterface.word = e.word
395398
}
396399

397400
func (codec *nonEmptyInterfaceCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
398401
nonEmptyInterface := (*nonEmptyInterface)(ptr)
399402
var i interface{}
400-
e := (*emptyInterface)(unsafe.Pointer(&i))
401-
e.typ = nonEmptyInterface.itab.typ
402-
e.word = nonEmptyInterface.word
403+
if nonEmptyInterface.itab != nil {
404+
e := (*emptyInterface)(unsafe.Pointer(&i))
405+
e.typ = nonEmptyInterface.itab.typ
406+
e.word = nonEmptyInterface.word
407+
}
403408
stream.WriteVal(i)
404409
}
405410

@@ -660,7 +665,11 @@ func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
660665
templateInterface := encoder.templateInterface
661666
templateInterface.word = ptr
662667
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
663-
marshaler := (*realInterface).(json.Marshaler)
668+
marshaler, ok := (*realInterface).(json.Marshaler)
669+
if !ok {
670+
stream.WriteVal(nil)
671+
return
672+
}
664673

665674
bytes, err := marshaler.MarshalJSON()
666675
if err != nil {

jsoniter_bool_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,22 @@ func Test_bool_can_be_null(t *testing.T) {
9292
obj := TestData{}
9393
data1 := []byte(`{"field": true}`)
9494
err := Unmarshal(data1, &obj)
95-
should.Equal(nil, err)
95+
should.NoError(err)
9696
should.Equal(true, obj.Field)
9797

9898
data2 := []byte(`{"field": null}`)
9999
err = Unmarshal(data2, &obj)
100-
should.Equal(nil, err)
100+
should.NoError(err)
101101
// Same behavior as stdlib, not touching the existing value.
102102
should.Equal(true, obj.Field)
103103

104104
// Checking stdlib behavior as well
105105
obj2 := TestData{}
106106
err = json.Unmarshal(data1, &obj2)
107-
should.Equal(nil, err)
107+
should.NoError(err)
108108
should.Equal(true, obj2.Field)
109109

110110
err = json.Unmarshal(data2, &obj2)
111-
should.Equal(nil, err)
111+
should.NoError(err)
112112
should.Equal(true, obj2.Field)
113113
}

jsoniter_enum_marshaler_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ func Test_custom_marshaler_on_enum(t *testing.T) {
4040
w := Wrapper{Payload: MyEnumB}
4141

4242
jb, err := Marshal(w)
43-
should.Equal(nil, err)
43+
should.NoError(err)
4444
should.Equal(`{"Payload":"foo-1"}`, string(jb))
4545

4646
var w2 Wrapper2
4747
err = Unmarshal(jb, &w2)
48-
should.Equal(nil, err)
48+
should.NoError(err)
4949
should.Equal(MyEnumB, w2.Payload)
5050
}

jsoniter_interface_test.go

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -329,13 +329,13 @@ func Test_nil_out_null_interface(t *testing.T) {
329329
data1 := []byte(`{"field": true}`)
330330

331331
err := Unmarshal(data1, &obj)
332-
should.Equal(nil, err)
332+
should.NoError(err)
333333
should.Equal(true, *(obj.Field.(*bool)))
334334

335335
data2 := []byte(`{"field": null}`)
336336

337337
err = Unmarshal(data2, &obj)
338-
should.Equal(nil, err)
338+
should.NoError(err)
339339
should.Equal(nil, obj.Field)
340340

341341
// Checking stdlib behavior matches.
@@ -344,11 +344,11 @@ func Test_nil_out_null_interface(t *testing.T) {
344344
}
345345

346346
err = json.Unmarshal(data1, &obj2)
347-
should.Equal(nil, err)
347+
should.NoError(err)
348348
should.Equal(true, *(obj2.Field.(*bool)))
349349

350350
err = json.Unmarshal(data2, &obj2)
351-
should.Equal(nil, err)
351+
should.NoError(err)
352352
should.Equal(nil, obj2.Field)
353353
}
354354

@@ -363,10 +363,77 @@ func Test_omitempty_nil_interface(t *testing.T) {
363363
}
364364

365365
js, err := json.Marshal(obj)
366-
should.Equal(nil, err)
366+
should.NoError(err)
367367
should.Equal("{}", string(js))
368368

369369
str, err := MarshalToString(obj)
370-
should.Equal(nil, err)
370+
should.NoError(err)
371371
should.Equal(string(js), str)
372372
}
373+
374+
func Test_omitempty_nil_nonempty_interface(t *testing.T) {
375+
type TestData struct {
376+
Field MyInterface `json:"field,omitempty"`
377+
}
378+
should := require.New(t)
379+
380+
obj := TestData{
381+
Field: nil,
382+
}
383+
384+
js, err := json.Marshal(obj)
385+
should.NoError(err)
386+
should.Equal("{}", string(js))
387+
388+
str, err := MarshalToString(obj)
389+
should.NoError(err)
390+
should.Equal(string(js), str)
391+
392+
obj.Field = MyString("hello")
393+
err = UnmarshalFromString(`{"field":null}`, &obj)
394+
should.NoError(err)
395+
should.Equal(nil, obj.Field)
396+
}
397+
398+
func Test_marshal_nil_marshaler_interface(t *testing.T) {
399+
type TestData struct {
400+
Field json.Marshaler `json:"field"`
401+
}
402+
should := require.New(t)
403+
404+
obj := TestData{
405+
Field: nil,
406+
}
407+
408+
js, err := json.Marshal(obj)
409+
should.NoError(err)
410+
should.Equal(`{"field":null}`, string(js))
411+
412+
str, err := MarshalToString(obj)
413+
should.NoError(err)
414+
should.Equal(string(js), str)
415+
}
416+
417+
func Test_marshal_nil_nonempty_interface(t *testing.T) {
418+
type TestData struct {
419+
Field MyInterface `json:"field"`
420+
}
421+
should := require.New(t)
422+
423+
obj := TestData{
424+
Field: nil,
425+
}
426+
427+
js, err := json.Marshal(obj)
428+
should.NoError(err)
429+
should.Equal(`{"field":null}`, string(js))
430+
431+
str, err := MarshalToString(obj)
432+
should.NoError(err)
433+
should.Equal(string(js), str)
434+
435+
obj.Field = MyString("hello")
436+
err = Unmarshal(js, &obj)
437+
should.NoError(err)
438+
should.Equal(nil, obj.Field)
439+
}

0 commit comments

Comments
 (0)