...

Source file src/github.com/json-iterator/go/config.go

Documentation: github.com/json-iterator/go

     1  package jsoniter
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"reflect"
     7  	"sync"
     8  	"unsafe"
     9  
    10  	"github.com/modern-go/concurrent"
    11  	"github.com/modern-go/reflect2"
    12  )
    13  
    14  // Config customize how the API should behave.
    15  // The API is created from Config by Froze.
    16  type Config struct {
    17  	IndentionStep                 int
    18  	MarshalFloatWith6Digits       bool
    19  	EscapeHTML                    bool
    20  	SortMapKeys                   bool
    21  	UseNumber                     bool
    22  	DisallowUnknownFields         bool
    23  	TagKey                        string
    24  	OnlyTaggedField               bool
    25  	ValidateJsonRawMessage        bool
    26  	ObjectFieldMustBeSimpleString bool
    27  	CaseSensitive                 bool
    28  }
    29  
    30  // API the public interface of this package.
    31  // Primary Marshal and Unmarshal.
    32  type API interface {
    33  	IteratorPool
    34  	StreamPool
    35  	MarshalToString(v interface{}) (string, error)
    36  	Marshal(v interface{}) ([]byte, error)
    37  	MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
    38  	UnmarshalFromString(str string, v interface{}) error
    39  	Unmarshal(data []byte, v interface{}) error
    40  	Get(data []byte, path ...interface{}) Any
    41  	NewEncoder(writer io.Writer) *Encoder
    42  	NewDecoder(reader io.Reader) *Decoder
    43  	Valid(data []byte) bool
    44  	RegisterExtension(extension Extension)
    45  	DecoderOf(typ reflect2.Type) ValDecoder
    46  	EncoderOf(typ reflect2.Type) ValEncoder
    47  }
    48  
    49  // ConfigDefault the default API
    50  var ConfigDefault = Config{
    51  	EscapeHTML: true,
    52  }.Froze()
    53  
    54  // ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior
    55  var ConfigCompatibleWithStandardLibrary = Config{
    56  	EscapeHTML:             true,
    57  	SortMapKeys:            true,
    58  	ValidateJsonRawMessage: true,
    59  }.Froze()
    60  
    61  // ConfigFastest marshals float with only 6 digits precision
    62  var ConfigFastest = Config{
    63  	EscapeHTML:                    false,
    64  	MarshalFloatWith6Digits:       true, // will lose precession
    65  	ObjectFieldMustBeSimpleString: true, // do not unescape object field
    66  }.Froze()
    67  
    68  type frozenConfig struct {
    69  	configBeforeFrozen            Config
    70  	sortMapKeys                   bool
    71  	indentionStep                 int
    72  	objectFieldMustBeSimpleString bool
    73  	onlyTaggedField               bool
    74  	disallowUnknownFields         bool
    75  	decoderCache                  *concurrent.Map
    76  	encoderCache                  *concurrent.Map
    77  	encoderExtension              Extension
    78  	decoderExtension              Extension
    79  	extraExtensions               []Extension
    80  	streamPool                    *sync.Pool
    81  	iteratorPool                  *sync.Pool
    82  	caseSensitive                 bool
    83  }
    84  
    85  func (cfg *frozenConfig) initCache() {
    86  	cfg.decoderCache = concurrent.NewMap()
    87  	cfg.encoderCache = concurrent.NewMap()
    88  }
    89  
    90  func (cfg *frozenConfig) addDecoderToCache(cacheKey uintptr, decoder ValDecoder) {
    91  	cfg.decoderCache.Store(cacheKey, decoder)
    92  }
    93  
    94  func (cfg *frozenConfig) addEncoderToCache(cacheKey uintptr, encoder ValEncoder) {
    95  	cfg.encoderCache.Store(cacheKey, encoder)
    96  }
    97  
    98  func (cfg *frozenConfig) getDecoderFromCache(cacheKey uintptr) ValDecoder {
    99  	decoder, found := cfg.decoderCache.Load(cacheKey)
   100  	if found {
   101  		return decoder.(ValDecoder)
   102  	}
   103  	return nil
   104  }
   105  
   106  func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder {
   107  	encoder, found := cfg.encoderCache.Load(cacheKey)
   108  	if found {
   109  		return encoder.(ValEncoder)
   110  	}
   111  	return nil
   112  }
   113  
   114  var cfgCache = concurrent.NewMap()
   115  
   116  func getFrozenConfigFromCache(cfg Config) *frozenConfig {
   117  	obj, found := cfgCache.Load(cfg)
   118  	if found {
   119  		return obj.(*frozenConfig)
   120  	}
   121  	return nil
   122  }
   123  
   124  func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) {
   125  	cfgCache.Store(cfg, frozenConfig)
   126  }
   127  
   128  // Froze forge API from config
   129  func (cfg Config) Froze() API {
   130  	api := &frozenConfig{
   131  		sortMapKeys:                   cfg.SortMapKeys,
   132  		indentionStep:                 cfg.IndentionStep,
   133  		objectFieldMustBeSimpleString: cfg.ObjectFieldMustBeSimpleString,
   134  		onlyTaggedField:               cfg.OnlyTaggedField,
   135  		disallowUnknownFields:         cfg.DisallowUnknownFields,
   136  		caseSensitive:                 cfg.CaseSensitive,
   137  	}
   138  	api.streamPool = &sync.Pool{
   139  		New: func() interface{} {
   140  			return NewStream(api, nil, 512)
   141  		},
   142  	}
   143  	api.iteratorPool = &sync.Pool{
   144  		New: func() interface{} {
   145  			return NewIterator(api)
   146  		},
   147  	}
   148  	api.initCache()
   149  	encoderExtension := EncoderExtension{}
   150  	decoderExtension := DecoderExtension{}
   151  	if cfg.MarshalFloatWith6Digits {
   152  		api.marshalFloatWith6Digits(encoderExtension)
   153  	}
   154  	if cfg.EscapeHTML {
   155  		api.escapeHTML(encoderExtension)
   156  	}
   157  	if cfg.UseNumber {
   158  		api.useNumber(decoderExtension)
   159  	}
   160  	if cfg.ValidateJsonRawMessage {
   161  		api.validateJsonRawMessage(encoderExtension)
   162  	}
   163  	api.encoderExtension = encoderExtension
   164  	api.decoderExtension = decoderExtension
   165  	api.configBeforeFrozen = cfg
   166  	return api
   167  }
   168  
   169  func (cfg Config) frozeWithCacheReuse(extraExtensions []Extension) *frozenConfig {
   170  	api := getFrozenConfigFromCache(cfg)
   171  	if api != nil {
   172  		return api
   173  	}
   174  	api = cfg.Froze().(*frozenConfig)
   175  	for _, extension := range extraExtensions {
   176  		api.RegisterExtension(extension)
   177  	}
   178  	addFrozenConfigToCache(cfg, api)
   179  	return api
   180  }
   181  
   182  func (cfg *frozenConfig) validateJsonRawMessage(extension EncoderExtension) {
   183  	encoder := &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
   184  		rawMessage := *(*json.RawMessage)(ptr)
   185  		iter := cfg.BorrowIterator([]byte(rawMessage))
   186  		defer cfg.ReturnIterator(iter)
   187  		iter.Read()
   188  		if iter.Error != nil && iter.Error != io.EOF {
   189  			stream.WriteRaw("null")
   190  		} else {
   191  			stream.WriteRaw(string(rawMessage))
   192  		}
   193  	}, func(ptr unsafe.Pointer) bool {
   194  		return len(*((*json.RawMessage)(ptr))) == 0
   195  	}}
   196  	extension[reflect2.TypeOfPtr((*json.RawMessage)(nil)).Elem()] = encoder
   197  	extension[reflect2.TypeOfPtr((*RawMessage)(nil)).Elem()] = encoder
   198  }
   199  
   200  func (cfg *frozenConfig) useNumber(extension DecoderExtension) {
   201  	extension[reflect2.TypeOfPtr((*interface{})(nil)).Elem()] = &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
   202  		exitingValue := *((*interface{})(ptr))
   203  		if exitingValue != nil && reflect.TypeOf(exitingValue).Kind() == reflect.Ptr {
   204  			iter.ReadVal(exitingValue)
   205  			return
   206  		}
   207  		if iter.WhatIsNext() == NumberValue {
   208  			*((*interface{})(ptr)) = json.Number(iter.readNumberAsString())
   209  		} else {
   210  			*((*interface{})(ptr)) = iter.Read()
   211  		}
   212  	}}
   213  }
   214  func (cfg *frozenConfig) getTagKey() string {
   215  	tagKey := cfg.configBeforeFrozen.TagKey
   216  	if tagKey == "" {
   217  		return "json"
   218  	}
   219  	return tagKey
   220  }
   221  
   222  func (cfg *frozenConfig) RegisterExtension(extension Extension) {
   223  	cfg.extraExtensions = append(cfg.extraExtensions, extension)
   224  	copied := cfg.configBeforeFrozen
   225  	cfg.configBeforeFrozen = copied
   226  }
   227  
   228  type lossyFloat32Encoder struct {
   229  }
   230  
   231  func (encoder *lossyFloat32Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
   232  	stream.WriteFloat32Lossy(*((*float32)(ptr)))
   233  }
   234  
   235  func (encoder *lossyFloat32Encoder) IsEmpty(ptr unsafe.Pointer) bool {
   236  	return *((*float32)(ptr)) == 0
   237  }
   238  
   239  type lossyFloat64Encoder struct {
   240  }
   241  
   242  func (encoder *lossyFloat64Encoder) Encode(ptr unsafe.Pointer, stream *Stream) {
   243  	stream.WriteFloat64Lossy(*((*float64)(ptr)))
   244  }
   245  
   246  func (encoder *lossyFloat64Encoder) IsEmpty(ptr unsafe.Pointer) bool {
   247  	return *((*float64)(ptr)) == 0
   248  }
   249  
   250  // EnableLossyFloatMarshalling keeps 10**(-6) precision
   251  // for float variables for better performance.
   252  func (cfg *frozenConfig) marshalFloatWith6Digits(extension EncoderExtension) {
   253  	// for better performance
   254  	extension[reflect2.TypeOfPtr((*float32)(nil)).Elem()] = &lossyFloat32Encoder{}
   255  	extension[reflect2.TypeOfPtr((*float64)(nil)).Elem()] = &lossyFloat64Encoder{}
   256  }
   257  
   258  type htmlEscapedStringEncoder struct {
   259  }
   260  
   261  func (encoder *htmlEscapedStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
   262  	str := *((*string)(ptr))
   263  	stream.WriteStringWithHTMLEscaped(str)
   264  }
   265  
   266  func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
   267  	return *((*string)(ptr)) == ""
   268  }
   269  
   270  func (cfg *frozenConfig) escapeHTML(encoderExtension EncoderExtension) {
   271  	encoderExtension[reflect2.TypeOfPtr((*string)(nil)).Elem()] = &htmlEscapedStringEncoder{}
   272  }
   273  
   274  func (cfg *frozenConfig) cleanDecoders() {
   275  	typeDecoders = map[string]ValDecoder{}
   276  	fieldDecoders = map[string]ValDecoder{}
   277  	*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
   278  }
   279  
   280  func (cfg *frozenConfig) cleanEncoders() {
   281  	typeEncoders = map[string]ValEncoder{}
   282  	fieldEncoders = map[string]ValEncoder{}
   283  	*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
   284  }
   285  
   286  func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {
   287  	stream := cfg.BorrowStream(nil)
   288  	defer cfg.ReturnStream(stream)
   289  	stream.WriteVal(v)
   290  	if stream.Error != nil {
   291  		return "", stream.Error
   292  	}
   293  	return string(stream.Buffer()), nil
   294  }
   295  
   296  func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {
   297  	stream := cfg.BorrowStream(nil)
   298  	defer cfg.ReturnStream(stream)
   299  	stream.WriteVal(v)
   300  	if stream.Error != nil {
   301  		return nil, stream.Error
   302  	}
   303  	result := stream.Buffer()
   304  	copied := make([]byte, len(result))
   305  	copy(copied, result)
   306  	return copied, nil
   307  }
   308  
   309  func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
   310  	if prefix != "" {
   311  		panic("prefix is not supported")
   312  	}
   313  	for _, r := range indent {
   314  		if r != ' ' {
   315  			panic("indent can only be space")
   316  		}
   317  	}
   318  	newCfg := cfg.configBeforeFrozen
   319  	newCfg.IndentionStep = len(indent)
   320  	return newCfg.frozeWithCacheReuse(cfg.extraExtensions).Marshal(v)
   321  }
   322  
   323  func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
   324  	data := []byte(str)
   325  	iter := cfg.BorrowIterator(data)
   326  	defer cfg.ReturnIterator(iter)
   327  	iter.ReadVal(v)
   328  	c := iter.nextToken()
   329  	if c == 0 {
   330  		if iter.Error == io.EOF {
   331  			return nil
   332  		}
   333  		return iter.Error
   334  	}
   335  	iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
   336  	return iter.Error
   337  }
   338  
   339  func (cfg *frozenConfig) Get(data []byte, path ...interface{}) Any {
   340  	iter := cfg.BorrowIterator(data)
   341  	defer cfg.ReturnIterator(iter)
   342  	return locatePath(iter, path)
   343  }
   344  
   345  func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error {
   346  	iter := cfg.BorrowIterator(data)
   347  	defer cfg.ReturnIterator(iter)
   348  	iter.ReadVal(v)
   349  	c := iter.nextToken()
   350  	if c == 0 {
   351  		if iter.Error == io.EOF {
   352  			return nil
   353  		}
   354  		return iter.Error
   355  	}
   356  	iter.ReportError("Unmarshal", "there are bytes left after unmarshal")
   357  	return iter.Error
   358  }
   359  
   360  func (cfg *frozenConfig) NewEncoder(writer io.Writer) *Encoder {
   361  	stream := NewStream(cfg, writer, 512)
   362  	return &Encoder{stream}
   363  }
   364  
   365  func (cfg *frozenConfig) NewDecoder(reader io.Reader) *Decoder {
   366  	iter := Parse(cfg, reader, 512)
   367  	return &Decoder{iter}
   368  }
   369  
   370  func (cfg *frozenConfig) Valid(data []byte) bool {
   371  	iter := cfg.BorrowIterator(data)
   372  	defer cfg.ReturnIterator(iter)
   373  	iter.Skip()
   374  	return iter.Error == nil
   375  }
   376  

View as plain text