diff --git a/feature_iter_object.go b/feature_iter_object.go index ddf0839..5a84b0f 100644 --- a/feature_iter_object.go +++ b/feature_iter_object.go @@ -84,7 +84,7 @@ func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool { return false } for iter.nextToken() == ',' { - field := string(iter.readObjectFieldAsBytes()) + field = string(iter.readObjectFieldAsBytes()) if !callback(iter, field) { return false } @@ -105,6 +105,46 @@ func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool { return false } +func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool { + c := iter.nextToken() + if c == '{' { + c = iter.nextToken() + if c == '"' { + iter.unreadByte() + field := iter.ReadString() + if iter.nextToken() != ':' { + iter.reportError("ReadMapCB", "expect : after object field") + return false + } + if !callback(iter, field) { + return false + } + for iter.nextToken() == ',' { + field = iter.ReadString() + if iter.nextToken() != ':' { + iter.reportError("ReadMapCB", "expect : after object field") + return false + } + if !callback(iter, field) { + return false + } + } + return true + } + if c == '}' { + return true + } + iter.reportError("ReadMapCB", `expect " after }`) + return false + } + if c == 'n' { + iter.skipFixedBytes(3) + return true // null + } + iter.reportError("ReadMapCB", `expect { or n`) + return false +} + func (iter *Iterator) readObjectStart() bool { c := iter.nextToken() if c == '{' { diff --git a/feature_reflect_map.go b/feature_reflect_map.go index 9c55830..8b93de7 100644 --- a/feature_reflect_map.go +++ b/feature_reflect_map.go @@ -25,7 +25,7 @@ func (decoder *mapDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if realVal.IsNil() { realVal.Set(reflect.MakeMap(realVal.Type())) } - iter.ReadObjectCB(func(iter *Iterator, keyStr string) bool { + iter.ReadMapCB(func(iter *Iterator, keyStr string) bool { elem := reflect.New(decoder.elemType) decoder.elemDecoder.decode(unsafe.Pointer(elem.Pointer()), iter) // to put into map, we have to use reflection diff --git a/jsoniter_map_test.go b/jsoniter_map_test.go index e1cab96..d85a02e 100644 --- a/jsoniter_map_test.go +++ b/jsoniter_map_test.go @@ -4,6 +4,7 @@ import ( "github.com/json-iterator/go/require" "math/big" "testing" + "encoding/json" ) func Test_read_map(t *testing.T) { @@ -101,3 +102,28 @@ func Test_decode_TextMarshaler_key_map(t *testing.T) { should.Nil(err) should.Equal(`{"1":"2"}`, str) } + + + +func Test_map_key_with_escaped_char(t *testing.T) { + type Ttest struct { + Map map[string]string + } + var jsonBytes = []byte(` + { + "Map":{ + "k\"ey": "val" + } + }`) + should := require.New(t) + { + var obj Ttest + should.Nil(json.Unmarshal(jsonBytes, &obj)) + should.Equal(map[string]string{"k\"ey":"val"}, obj.Map) + } + { + var obj Ttest + should.Nil(Unmarshal(jsonBytes, &obj)) + should.Equal(map[string]string{"k\"ey":"val"}, obj.Map) + } +}