 aa40ebb417
			
		
	
	aa40ebb417
	
	
	
		
			
			full diff: https://github.com/json-iterator/go/compare/v1.1.9...v1.1.10 - Fix 459 map keys of custom types should serialize using MarshalText when available - Fix potential panic in (*stringAny).ToInt64 and (*stringAny).ToUint64 (see 450) - Fix 449 do NOT marshal the field whose name start with underscore - Reuse stream buffer and remove flush in (*Stream).WriteMore(see 441 440) - Fix 421 simplify the error string returned by the decoder when it meets error unmarshaling anonymous structs - Fix 389 411 do NOT marshal the json.RawMessage type field whose real type is integer/float as "null" with ValidateJsonRawMessage option enabled - Fix 326 do Not marshal private field after calling extra.SetNamingStrategy() to register naming strategy extension Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
		
			
				
	
	
		
			347 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			347 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package jsoniter
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"github.com/modern-go/reflect2"
 | |
| 	"io"
 | |
| 	"reflect"
 | |
| 	"sort"
 | |
| 	"unsafe"
 | |
| )
 | |
| 
 | |
| func decoderOfMap(ctx *ctx, typ reflect2.Type) ValDecoder {
 | |
| 	mapType := typ.(*reflect2.UnsafeMapType)
 | |
| 	keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), mapType.Key())
 | |
| 	elemDecoder := decoderOfType(ctx.append("[mapElem]"), mapType.Elem())
 | |
| 	return &mapDecoder{
 | |
| 		mapType:     mapType,
 | |
| 		keyType:     mapType.Key(),
 | |
| 		elemType:    mapType.Elem(),
 | |
| 		keyDecoder:  keyDecoder,
 | |
| 		elemDecoder: elemDecoder,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder {
 | |
| 	mapType := typ.(*reflect2.UnsafeMapType)
 | |
| 	if ctx.sortMapKeys {
 | |
| 		return &sortKeysMapEncoder{
 | |
| 			mapType:     mapType,
 | |
| 			keyEncoder:  encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
 | |
| 			elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
 | |
| 		}
 | |
| 	}
 | |
| 	return &mapEncoder{
 | |
| 		mapType:     mapType,
 | |
| 		keyEncoder:  encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
 | |
| 		elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
 | |
| 	decoder := ctx.decoderExtension.CreateMapKeyDecoder(typ)
 | |
| 	if decoder != nil {
 | |
| 		return decoder
 | |
| 	}
 | |
| 	for _, extension := range ctx.extraExtensions {
 | |
| 		decoder := extension.CreateMapKeyDecoder(typ)
 | |
| 		if decoder != nil {
 | |
| 			return decoder
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	ptrType := reflect2.PtrTo(typ)
 | |
| 	if ptrType.Implements(unmarshalerType) {
 | |
| 		return &referenceDecoder{
 | |
| 			&unmarshalerDecoder{
 | |
| 				valType: ptrType,
 | |
| 			},
 | |
| 		}
 | |
| 	}
 | |
| 	if typ.Implements(unmarshalerType) {
 | |
| 		return &unmarshalerDecoder{
 | |
| 			valType: typ,
 | |
| 		}
 | |
| 	}
 | |
| 	if ptrType.Implements(textUnmarshalerType) {
 | |
| 		return &referenceDecoder{
 | |
| 			&textUnmarshalerDecoder{
 | |
| 				valType: ptrType,
 | |
| 			},
 | |
| 		}
 | |
| 	}
 | |
| 	if typ.Implements(textUnmarshalerType) {
 | |
| 		return &textUnmarshalerDecoder{
 | |
| 			valType: typ,
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	switch typ.Kind() {
 | |
| 	case reflect.String:
 | |
| 		return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
 | |
| 	case reflect.Bool,
 | |
| 		reflect.Uint8, reflect.Int8,
 | |
| 		reflect.Uint16, reflect.Int16,
 | |
| 		reflect.Uint32, reflect.Int32,
 | |
| 		reflect.Uint64, reflect.Int64,
 | |
| 		reflect.Uint, reflect.Int,
 | |
| 		reflect.Float32, reflect.Float64,
 | |
| 		reflect.Uintptr:
 | |
| 		typ = reflect2.DefaultTypeOfKind(typ.Kind())
 | |
| 		return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
 | |
| 	default:
 | |
| 		return &lazyErrorDecoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
 | |
| 	encoder := ctx.encoderExtension.CreateMapKeyEncoder(typ)
 | |
| 	if encoder != nil {
 | |
| 		return encoder
 | |
| 	}
 | |
| 	for _, extension := range ctx.extraExtensions {
 | |
| 		encoder := extension.CreateMapKeyEncoder(typ)
 | |
| 		if encoder != nil {
 | |
| 			return encoder
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if typ == textMarshalerType {
 | |
| 		return &directTextMarshalerEncoder{
 | |
| 			stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
 | |
| 		}
 | |
| 	}
 | |
| 	if typ.Implements(textMarshalerType) {
 | |
| 		return &textMarshalerEncoder{
 | |
| 			valType:       typ,
 | |
| 			stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	switch typ.Kind() {
 | |
| 	case reflect.String:
 | |
| 		return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
 | |
| 	case reflect.Bool,
 | |
| 		reflect.Uint8, reflect.Int8,
 | |
| 		reflect.Uint16, reflect.Int16,
 | |
| 		reflect.Uint32, reflect.Int32,
 | |
| 		reflect.Uint64, reflect.Int64,
 | |
| 		reflect.Uint, reflect.Int,
 | |
| 		reflect.Float32, reflect.Float64,
 | |
| 		reflect.Uintptr:
 | |
| 		typ = reflect2.DefaultTypeOfKind(typ.Kind())
 | |
| 		return &numericMapKeyEncoder{encoderOfType(ctx, typ)}
 | |
| 	default:
 | |
| 		if typ.Kind() == reflect.Interface {
 | |
| 			return &dynamicMapKeyEncoder{ctx, typ}
 | |
| 		}
 | |
| 		return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type mapDecoder struct {
 | |
| 	mapType     *reflect2.UnsafeMapType
 | |
| 	keyType     reflect2.Type
 | |
| 	elemType    reflect2.Type
 | |
| 	keyDecoder  ValDecoder
 | |
| 	elemDecoder ValDecoder
 | |
| }
 | |
| 
 | |
| func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
 | |
| 	mapType := decoder.mapType
 | |
| 	c := iter.nextToken()
 | |
| 	if c == 'n' {
 | |
| 		iter.skipThreeBytes('u', 'l', 'l')
 | |
| 		*(*unsafe.Pointer)(ptr) = nil
 | |
| 		mapType.UnsafeSet(ptr, mapType.UnsafeNew())
 | |
| 		return
 | |
| 	}
 | |
| 	if mapType.UnsafeIsNil(ptr) {
 | |
| 		mapType.UnsafeSet(ptr, mapType.UnsafeMakeMap(0))
 | |
| 	}
 | |
| 	if c != '{' {
 | |
| 		iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
 | |
| 		return
 | |
| 	}
 | |
| 	c = iter.nextToken()
 | |
| 	if c == '}' {
 | |
| 		return
 | |
| 	}
 | |
| 	iter.unreadByte()
 | |
| 	key := decoder.keyType.UnsafeNew()
 | |
| 	decoder.keyDecoder.Decode(key, iter)
 | |
| 	c = iter.nextToken()
 | |
| 	if c != ':' {
 | |
| 		iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
 | |
| 		return
 | |
| 	}
 | |
| 	elem := decoder.elemType.UnsafeNew()
 | |
| 	decoder.elemDecoder.Decode(elem, iter)
 | |
| 	decoder.mapType.UnsafeSetIndex(ptr, key, elem)
 | |
| 	for c = iter.nextToken(); c == ','; c = iter.nextToken() {
 | |
| 		key := decoder.keyType.UnsafeNew()
 | |
| 		decoder.keyDecoder.Decode(key, iter)
 | |
| 		c = iter.nextToken()
 | |
| 		if c != ':' {
 | |
| 			iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
 | |
| 			return
 | |
| 		}
 | |
| 		elem := decoder.elemType.UnsafeNew()
 | |
| 		decoder.elemDecoder.Decode(elem, iter)
 | |
| 		decoder.mapType.UnsafeSetIndex(ptr, key, elem)
 | |
| 	}
 | |
| 	if c != '}' {
 | |
| 		iter.ReportError("ReadMapCB", `expect }, but found `+string([]byte{c}))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type numericMapKeyDecoder struct {
 | |
| 	decoder ValDecoder
 | |
| }
 | |
| 
 | |
| func (decoder *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
 | |
| 	c := iter.nextToken()
 | |
| 	if c != '"' {
 | |
| 		iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c}))
 | |
| 		return
 | |
| 	}
 | |
| 	decoder.decoder.Decode(ptr, iter)
 | |
| 	c = iter.nextToken()
 | |
| 	if c != '"' {
 | |
| 		iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c}))
 | |
| 		return
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type numericMapKeyEncoder struct {
 | |
| 	encoder ValEncoder
 | |
| }
 | |
| 
 | |
| func (encoder *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
 | |
| 	stream.writeByte('"')
 | |
| 	encoder.encoder.Encode(ptr, stream)
 | |
| 	stream.writeByte('"')
 | |
| }
 | |
| 
 | |
| func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| type dynamicMapKeyEncoder struct {
 | |
| 	ctx     *ctx
 | |
| 	valType reflect2.Type
 | |
| }
 | |
| 
 | |
| func (encoder *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
 | |
| 	obj := encoder.valType.UnsafeIndirect(ptr)
 | |
| 	encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream)
 | |
| }
 | |
| 
 | |
| func (encoder *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
 | |
| 	obj := encoder.valType.UnsafeIndirect(ptr)
 | |
| 	return encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj))
 | |
| }
 | |
| 
 | |
| type mapEncoder struct {
 | |
| 	mapType     *reflect2.UnsafeMapType
 | |
| 	keyEncoder  ValEncoder
 | |
| 	elemEncoder ValEncoder
 | |
| }
 | |
| 
 | |
| func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
 | |
| 	if *(*unsafe.Pointer)(ptr) == nil {
 | |
| 		stream.WriteNil()
 | |
| 		return
 | |
| 	}
 | |
| 	stream.WriteObjectStart()
 | |
| 	iter := encoder.mapType.UnsafeIterate(ptr)
 | |
| 	for i := 0; iter.HasNext(); i++ {
 | |
| 		if i != 0 {
 | |
| 			stream.WriteMore()
 | |
| 		}
 | |
| 		key, elem := iter.UnsafeNext()
 | |
| 		encoder.keyEncoder.Encode(key, stream)
 | |
| 		if stream.indention > 0 {
 | |
| 			stream.writeTwoBytes(byte(':'), byte(' '))
 | |
| 		} else {
 | |
| 			stream.writeByte(':')
 | |
| 		}
 | |
| 		encoder.elemEncoder.Encode(elem, stream)
 | |
| 	}
 | |
| 	stream.WriteObjectEnd()
 | |
| }
 | |
| 
 | |
| func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
 | |
| 	iter := encoder.mapType.UnsafeIterate(ptr)
 | |
| 	return !iter.HasNext()
 | |
| }
 | |
| 
 | |
| type sortKeysMapEncoder struct {
 | |
| 	mapType     *reflect2.UnsafeMapType
 | |
| 	keyEncoder  ValEncoder
 | |
| 	elemEncoder ValEncoder
 | |
| }
 | |
| 
 | |
| func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
 | |
| 	if *(*unsafe.Pointer)(ptr) == nil {
 | |
| 		stream.WriteNil()
 | |
| 		return
 | |
| 	}
 | |
| 	stream.WriteObjectStart()
 | |
| 	mapIter := encoder.mapType.UnsafeIterate(ptr)
 | |
| 	subStream := stream.cfg.BorrowStream(nil)
 | |
| 	subStream.Attachment = stream.Attachment
 | |
| 	subIter := stream.cfg.BorrowIterator(nil)
 | |
| 	keyValues := encodedKeyValues{}
 | |
| 	for mapIter.HasNext() {
 | |
| 		key, elem := mapIter.UnsafeNext()
 | |
| 		subStreamIndex := subStream.Buffered()
 | |
| 		encoder.keyEncoder.Encode(key, subStream)
 | |
| 		if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil {
 | |
| 			stream.Error = subStream.Error
 | |
| 		}
 | |
| 		encodedKey := subStream.Buffer()[subStreamIndex:]
 | |
| 		subIter.ResetBytes(encodedKey)
 | |
| 		decodedKey := subIter.ReadString()
 | |
| 		if stream.indention > 0 {
 | |
| 			subStream.writeTwoBytes(byte(':'), byte(' '))
 | |
| 		} else {
 | |
| 			subStream.writeByte(':')
 | |
| 		}
 | |
| 		encoder.elemEncoder.Encode(elem, subStream)
 | |
| 		keyValues = append(keyValues, encodedKV{
 | |
| 			key:      decodedKey,
 | |
| 			keyValue: subStream.Buffer()[subStreamIndex:],
 | |
| 		})
 | |
| 	}
 | |
| 	sort.Sort(keyValues)
 | |
| 	for i, keyValue := range keyValues {
 | |
| 		if i != 0 {
 | |
| 			stream.WriteMore()
 | |
| 		}
 | |
| 		stream.Write(keyValue.keyValue)
 | |
| 	}
 | |
| 	if subStream.Error != nil && stream.Error == nil {
 | |
| 		stream.Error = subStream.Error
 | |
| 	}
 | |
| 	stream.WriteObjectEnd()
 | |
| 	stream.cfg.ReturnStream(subStream)
 | |
| 	stream.cfg.ReturnIterator(subIter)
 | |
| }
 | |
| 
 | |
| func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
 | |
| 	iter := encoder.mapType.UnsafeIterate(ptr)
 | |
| 	return !iter.HasNext()
 | |
| }
 | |
| 
 | |
| type encodedKeyValues []encodedKV
 | |
| 
 | |
| type encodedKV struct {
 | |
| 	key      string
 | |
| 	keyValue []byte
 | |
| }
 | |
| 
 | |
| func (sv encodedKeyValues) Len() int           { return len(sv) }
 | |
| func (sv encodedKeyValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
 | |
| func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key }
 |