Skip to content

Commit 1f58120

Browse files
committed
Always skip unexported fields when encoding
Skip creating encoders for unexported fields. They are not participating in JSON marshaling anyway. This allows using unexported fields of non-marshalable types in structs. As a side-effect of this change it's no longer possible to marshal unexported JSON fields by adding a custom type extenstion. It seems this is desired behavior since it matches standard library and jsoniter already disallows `json:"-"` fields from participating in custom extensions. Fixes #174.
1 parent 6ed2715 commit 1f58120

3 files changed

+60
-4
lines changed

feature_reflect_extension.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
227227
bindings := []*Binding{}
228228
for i := 0; i < typ.NumField(); i++ {
229229
field := typ.Field(i)
230+
if unicode.IsLower([]rune(field.Name)[0]) {
231+
continue
232+
}
230233
tag := field.Tag.Get(cfg.getTagKey())
231234
tagParts := strings.Split(tag, ",")
232235
if tag == "-" {

jsoniter_customize_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package jsoniter
22

33
import (
44
"encoding/json"
5-
"github.com/stretchr/testify/require"
65
"strconv"
76
"testing"
87
"time"
98
"unsafe"
9+
10+
"github.com/stretchr/testify/require"
1011
)
1112

1213
func Test_customize_type_decoder(t *testing.T) {
@@ -82,7 +83,7 @@ func Test_customize_field_decoder(t *testing.T) {
8283
}
8384

8485
type TestObject1 struct {
85-
field1 string
86+
Field1 string
8687
}
8788

8889
type testExtension struct {
@@ -93,7 +94,7 @@ func (extension *testExtension) UpdateStructDescriptor(structDescriptor *StructD
9394
if structDescriptor.Type.String() != "jsoniter.TestObject1" {
9495
return
9596
}
96-
binding := structDescriptor.GetField("field1")
97+
binding := structDescriptor.GetField("Field1")
9798
binding.Encoder = &funcEncoder{fun: func(ptr unsafe.Pointer, stream *Stream) {
9899
str := *((*string)(ptr))
99100
val, _ := strconv.Atoi(str)
@@ -112,7 +113,7 @@ func Test_customize_field_by_extension(t *testing.T) {
112113
obj := TestObject1{}
113114
err := UnmarshalFromString(`{"field-1": 100}`, &obj)
114115
should.Nil(err)
115-
should.Equal("100", obj.field1)
116+
should.Equal("100", obj.Field1)
116117
str, err := MarshalToString(obj)
117118
should.Nil(err)
118119
should.Equal(`{"field-1":100}`, str)

jsoniter_struct_encoder_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package jsoniter
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
"time"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func Test_encode_unexported_field(t *testing.T) {
12+
type TestData struct {
13+
a int
14+
b <-chan int
15+
C int
16+
d *time.Timer
17+
}
18+
19+
should := require.New(t)
20+
21+
testChan := make(<-chan int, 10)
22+
testTimer := time.NewTimer(10 * time.Second)
23+
24+
obj := &TestData{
25+
a: 42,
26+
b: testChan,
27+
C: 21,
28+
d: testTimer,
29+
}
30+
31+
jb, err := json.Marshal(obj)
32+
should.NoError(err)
33+
should.Equal([]byte(`{"C":21}`), jb)
34+
35+
err = json.Unmarshal([]byte(`{"a": 444, "b":"bad", "C":55, "d":{"not": "a timer"}}`), obj)
36+
should.NoError(err)
37+
should.Equal(42, obj.a)
38+
should.Equal(testChan, obj.b)
39+
should.Equal(55, obj.C)
40+
should.Equal(testTimer, obj.d)
41+
42+
jb, err = Marshal(obj)
43+
should.NoError(err)
44+
should.Equal(jb, []byte(`{"C":55}`))
45+
46+
err = Unmarshal([]byte(`{"a": 444, "b":"bad", "C":256, "d":{"not":"a timer"}}`), obj)
47+
should.NoError(err)
48+
should.Equal(42, obj.a)
49+
should.Equal(testChan, obj.b)
50+
should.Equal(256, obj.C)
51+
should.Equal(testTimer, obj.d)
52+
}

0 commit comments

Comments
 (0)