Skip to content

Commit 71f74dc

Browse files
committed
implement #230 DisallowUnknownFields option added
1 parent 7990317 commit 71f74dc

File tree

6 files changed

+60
-16
lines changed

6 files changed

+60
-16
lines changed

api_tests/decoder_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package test
2+
3+
import (
4+
"bytes"
5+
"github.com/json-iterator/go"
6+
"github.com/stretchr/testify/require"
7+
"testing"
8+
)
9+
10+
func Test_disallowUnknownFields(t *testing.T) {
11+
should := require.New(t)
12+
type TestObject struct{}
13+
var obj TestObject
14+
decoder := jsoniter.NewDecoder(bytes.NewBufferString(`{"field1":100}`))
15+
decoder.DisallowUnknownFields()
16+
should.Error(decoder.Decode(&obj))
17+
}

feature_adapter.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,23 @@ func (adapter *Decoder) Buffered() io.Reader {
9595
return bytes.NewReader(remaining)
9696
}
9797

98-
// UseNumber for number JSON element, use float64 or json.NumberValue (alias of string)
98+
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
99+
// Number instead of as a float64.
99100
func (adapter *Decoder) UseNumber() {
100101
cfg := adapter.iter.cfg.configBeforeFrozen
101102
cfg.UseNumber = true
102103
adapter.iter.cfg = cfg.frozeWithCacheReuse()
103104
}
104105

106+
// DisallowUnknownFields causes the Decoder to return an error when the destination
107+
// is a struct and the input contains object keys which do not match any
108+
// non-ignored, exported fields in the destination.
109+
func (adapter *Decoder) DisallowUnknownFields() {
110+
cfg := adapter.iter.cfg.configBeforeFrozen
111+
cfg.DisallowUnknownFields = true
112+
adapter.iter.cfg = cfg.frozeWithCacheReuse()
113+
}
114+
105115
// NewEncoder same as json.NewEncoder
106116
func NewEncoder(writer io.Writer) *Encoder {
107117
return ConfigDefault.NewEncoder(writer)

feature_config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type Config struct {
1616
EscapeHTML bool
1717
SortMapKeys bool
1818
UseNumber bool
19+
DisallowUnknownFields bool
1920
TagKey string
2021
OnlyTaggedField bool
2122
ValidateJsonRawMessage bool
@@ -65,6 +66,7 @@ func (cfg Config) Froze() API {
6566
indentionStep: cfg.IndentionStep,
6667
objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString,
6768
onlyTaggedField: cfg.OnlyTaggedField,
69+
disallowUnknownFields: cfg.DisallowUnknownFields,
6870
streamPool: make(chan *Stream, 16),
6971
iteratorPool: make(chan *Iterator, 16),
7072
}

feature_config_without_sync_map.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type frozenConfig struct {
1313
indentionStep int
1414
objectFieldMustBeSimpleString bool
1515
onlyTaggedField bool
16+
disallowUnknownFields bool
1617
cacheLock *sync.RWMutex
1718
decoderCache map[reflect.Type]ValDecoder
1819
encoderCache map[reflect.Type]ValEncoder

feature_reflect_object.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
9999
for k, binding := range bindings {
100100
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
101101
}
102-
return createStructDecoder(typ, fields)
102+
return createStructDecoder(cfg, typ, fields)
103103
}
104104

105105
type structFieldEncoder struct {

feature_reflect_struct_decoder.go

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import (
88
"unsafe"
99
)
1010

11-
func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
11+
func createStructDecoder(cfg *frozenConfig, typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
12+
if cfg.disallowUnknownFields {
13+
return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true}
14+
}
1215
knownHash := map[int32]struct{}{
1316
0: {},
1417
}
@@ -20,7 +23,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
2023
fieldHash := calcHash(fieldName)
2124
_, known := knownHash[fieldHash]
2225
if known {
23-
return &generalStructDecoder{typ, fields}
26+
return &generalStructDecoder{typ, fields, false}
2427
}
2528
knownHash[fieldHash] = struct{}{}
2629
return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}
@@ -34,7 +37,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
3437
fieldHash := calcHash(fieldName)
3538
_, known := knownHash[fieldHash]
3639
if known {
37-
return &generalStructDecoder{typ, fields}
40+
return &generalStructDecoder{typ, fields, false}
3841
}
3942
knownHash[fieldHash] = struct{}{}
4043
if fieldHash1 == 0 {
@@ -57,7 +60,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
5760
fieldHash := calcHash(fieldName)
5861
_, known := knownHash[fieldHash]
5962
if known {
60-
return &generalStructDecoder{typ, fields}
63+
return &generalStructDecoder{typ, fields, false}
6164
}
6265
knownHash[fieldHash] = struct{}{}
6366
if fieldName1 == 0 {
@@ -88,7 +91,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
8891
fieldHash := calcHash(fieldName)
8992
_, known := knownHash[fieldHash]
9093
if known {
91-
return &generalStructDecoder{typ, fields}
94+
return &generalStructDecoder{typ, fields, false}
9295
}
9396
knownHash[fieldHash] = struct{}{}
9497
if fieldName1 == 0 {
@@ -125,7 +128,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
125128
fieldHash := calcHash(fieldName)
126129
_, known := knownHash[fieldHash]
127130
if known {
128-
return &generalStructDecoder{typ, fields}
131+
return &generalStructDecoder{typ, fields, false}
129132
}
130133
knownHash[fieldHash] = struct{}{}
131134
if fieldName1 == 0 {
@@ -168,7 +171,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
168171
fieldHash := calcHash(fieldName)
169172
_, known := knownHash[fieldHash]
170173
if known {
171-
return &generalStructDecoder{typ, fields}
174+
return &generalStructDecoder{typ, fields, false}
172175
}
173176
knownHash[fieldHash] = struct{}{}
174177
if fieldName1 == 0 {
@@ -217,7 +220,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
217220
fieldHash := calcHash(fieldName)
218221
_, known := knownHash[fieldHash]
219222
if known {
220-
return &generalStructDecoder{typ, fields}
223+
return &generalStructDecoder{typ, fields, false}
221224
}
222225
knownHash[fieldHash] = struct{}{}
223226
if fieldName1 == 0 {
@@ -272,7 +275,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
272275
fieldHash := calcHash(fieldName)
273276
_, known := knownHash[fieldHash]
274277
if known {
275-
return &generalStructDecoder{typ, fields}
278+
return &generalStructDecoder{typ, fields, false}
276279
}
277280
knownHash[fieldHash] = struct{}{}
278281
if fieldName1 == 0 {
@@ -333,7 +336,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
333336
fieldHash := calcHash(fieldName)
334337
_, known := knownHash[fieldHash]
335338
if known {
336-
return &generalStructDecoder{typ, fields}
339+
return &generalStructDecoder{typ, fields, false}
337340
}
338341
knownHash[fieldHash] = struct{}{}
339342
if fieldName1 == 0 {
@@ -400,7 +403,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
400403
fieldHash := calcHash(fieldName)
401404
_, known := knownHash[fieldHash]
402405
if known {
403-
return &generalStructDecoder{typ, fields}
406+
return &generalStructDecoder{typ, fields, false}
404407
}
405408
knownHash[fieldHash] = struct{}{}
406409
if fieldName1 == 0 {
@@ -447,12 +450,13 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
447450
fieldName9, fieldDecoder9,
448451
fieldName10, fieldDecoder10}
449452
}
450-
return &generalStructDecoder{typ, fields}
453+
return &generalStructDecoder{typ, fields, false}
451454
}
452455

453456
type generalStructDecoder struct {
454-
typ reflect.Type
455-
fields map[string]*structFieldDecoder
457+
typ reflect.Type
458+
fields map[string]*structFieldDecoder
459+
disallowUnknownFields bool
456460
}
457461

458462
func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
@@ -473,6 +477,11 @@ func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
473477
}
474478
fieldDecoder := decoder.fields[strings.ToLower(field)]
475479
if fieldDecoder == nil {
480+
if decoder.disallowUnknownFields {
481+
iter.ReportError("ReadObject", "found unknown field: "+field)
482+
iter.Skip()
483+
return
484+
}
476485
iter.Skip()
477486
} else {
478487
fieldDecoder.Decode(ptr, iter)
@@ -490,6 +499,11 @@ func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
490499
}
491500
fieldDecoder = decoder.fields[strings.ToLower(field)]
492501
if fieldDecoder == nil {
502+
if decoder.disallowUnknownFields {
503+
iter.ReportError("ReadObject", "found unknown field: "+field)
504+
iter.Skip()
505+
return
506+
}
493507
iter.Skip()
494508
} else {
495509
fieldDecoder.Decode(ptr, iter)

0 commit comments

Comments
 (0)