Bläddra i källkod

implement #230 DisallowUnknownFields option added

Tao Wen 7 år sedan
förälder
incheckning
71f74dc71e

+ 17 - 0
api_tests/decoder_test.go

@@ -0,0 +1,17 @@
+package test
+
+import (
+	"bytes"
+	"github.com/json-iterator/go"
+	"github.com/stretchr/testify/require"
+	"testing"
+)
+
+func Test_disallowUnknownFields(t *testing.T) {
+	should := require.New(t)
+	type TestObject struct{}
+	var obj TestObject
+	decoder := jsoniter.NewDecoder(bytes.NewBufferString(`{"field1":100}`))
+	decoder.DisallowUnknownFields()
+	should.Error(decoder.Decode(&obj))
+}

+ 11 - 1
feature_adapter.go

@@ -95,13 +95,23 @@ func (adapter *Decoder) Buffered() io.Reader {
 	return bytes.NewReader(remaining)
 }
 
-// UseNumber for number JSON element, use float64 or json.NumberValue (alias of string)
+// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
+// Number instead of as a float64.
 func (adapter *Decoder) UseNumber() {
 	cfg := adapter.iter.cfg.configBeforeFrozen
 	cfg.UseNumber = true
 	adapter.iter.cfg = cfg.frozeWithCacheReuse()
 }
 
+// DisallowUnknownFields causes the Decoder to return an error when the destination
+// is a struct and the input contains object keys which do not match any
+// non-ignored, exported fields in the destination.
+func (adapter *Decoder) DisallowUnknownFields() {
+	cfg := adapter.iter.cfg.configBeforeFrozen
+	cfg.DisallowUnknownFields = true
+	adapter.iter.cfg = cfg.frozeWithCacheReuse()
+}
+
 // NewEncoder same as json.NewEncoder
 func NewEncoder(writer io.Writer) *Encoder {
 	return ConfigDefault.NewEncoder(writer)

+ 2 - 0
feature_config.go

@@ -16,6 +16,7 @@ type Config struct {
 	EscapeHTML                    bool
 	SortMapKeys                   bool
 	UseNumber                     bool
+	DisallowUnknownFields         bool
 	TagKey                        string
 	OnlyTaggedField               bool
 	ValidateJsonRawMessage        bool
@@ -65,6 +66,7 @@ func (cfg Config) Froze() API {
 		indentionStep:                 cfg.IndentionStep,
 		objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString,
 		onlyTaggedField:               cfg.OnlyTaggedField,
+		disallowUnknownFields:         cfg.DisallowUnknownFields,
 		streamPool:                    make(chan *Stream, 16),
 		iteratorPool:                  make(chan *Iterator, 16),
 	}

+ 1 - 0
feature_config_without_sync_map.go

@@ -13,6 +13,7 @@ type frozenConfig struct {
 	indentionStep                 int
 	objectFieldMustBeSimpleString bool
 	onlyTaggedField               bool
+	disallowUnknownFields         bool
 	cacheLock                     *sync.RWMutex
 	decoderCache                  map[reflect.Type]ValDecoder
 	encoderCache                  map[reflect.Type]ValEncoder

+ 1 - 1
feature_reflect_object.go

@@ -99,7 +99,7 @@ func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDeco
 	for k, binding := range bindings {
 		fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
 	}
-	return createStructDecoder(typ, fields)
+	return createStructDecoder(cfg, typ, fields)
 }
 
 type structFieldEncoder struct {

+ 28 - 14
feature_reflect_struct_decoder.go

@@ -8,7 +8,10 @@ import (
 	"unsafe"
 )
 
-func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
+func createStructDecoder(cfg *frozenConfig, typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
+	if cfg.disallowUnknownFields {
+		return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true}
+	}
 	knownHash := map[int32]struct{}{
 		0: {},
 	}
@@ -20,7 +23,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}
@@ -34,7 +37,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldHash1 == 0 {
@@ -57,7 +60,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -88,7 +91,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -125,7 +128,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -168,7 +171,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -217,7 +220,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -272,7 +275,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -333,7 +336,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -400,7 +403,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}
+				return &generalStructDecoder{typ, fields, false}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -447,12 +450,13 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldName9, fieldDecoder9,
 			fieldName10, fieldDecoder10}
 	}
-	return &generalStructDecoder{typ, fields}
+	return &generalStructDecoder{typ, fields, false}
 }
 
 type generalStructDecoder struct {
-	typ    reflect.Type
-	fields map[string]*structFieldDecoder
+	typ                   reflect.Type
+	fields                map[string]*structFieldDecoder
+	disallowUnknownFields bool
 }
 
 func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
@@ -473,6 +477,11 @@ func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
 	}
 	fieldDecoder := decoder.fields[strings.ToLower(field)]
 	if fieldDecoder == nil {
+		if decoder.disallowUnknownFields {
+			iter.ReportError("ReadObject", "found unknown field: "+field)
+			iter.Skip()
+			return
+		}
 		iter.Skip()
 	} else {
 		fieldDecoder.Decode(ptr, iter)
@@ -490,6 +499,11 @@ func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
 		}
 		fieldDecoder = decoder.fields[strings.ToLower(field)]
 		if fieldDecoder == nil {
+			if decoder.disallowUnknownFields {
+				iter.ReportError("ReadObject", "found unknown field: "+field)
+				iter.Skip()
+				return
+			}
 			iter.Skip()
 		} else {
 			fieldDecoder.Decode(ptr, iter)