mirror of
https://github.com/json-iterator/go.git
synced 2025-05-13 21:36:29 +02:00
document public symbols
This commit is contained in:
parent
46574e7d09
commit
f0487718f6
@ -160,8 +160,8 @@ type tolerateEmptyArrayDecoder struct {
|
||||
func (decoder *tolerateEmptyArrayDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if iter.WhatIsNext() == jsoniter.Array {
|
||||
iter.Skip()
|
||||
newIter := iter.Config().BorrowIterator([]byte("{}"))
|
||||
defer iter.Config().ReturnIterator(newIter)
|
||||
newIter := iter.Pool().BorrowIterator([]byte("{}"))
|
||||
defer iter.Pool().ReturnIterator(newIter)
|
||||
decoder.valDecoder.Decode(ptr, newIter)
|
||||
} else {
|
||||
decoder.valDecoder.Decode(ptr, iter)
|
||||
@ -202,8 +202,8 @@ func (decoder *fuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It
|
||||
default:
|
||||
iter.ReportError("fuzzyIntegerDecoder", "not number or string")
|
||||
}
|
||||
newIter := iter.Config().BorrowIterator([]byte(str))
|
||||
defer iter.Config().ReturnIterator(newIter)
|
||||
newIter := iter.Pool().BorrowIterator([]byte(str))
|
||||
defer iter.Pool().ReturnIterator(newIter)
|
||||
isFloat := strings.IndexByte(str, '.') != -1
|
||||
decoder.fun(isFloat, ptr, newIter)
|
||||
if newIter.Error != nil {
|
||||
@ -222,8 +222,8 @@ func (decoder *fuzzyFloat32Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It
|
||||
*((*float32)(ptr)) = iter.ReadFloat32()
|
||||
case jsoniter.String:
|
||||
str = iter.ReadString()
|
||||
newIter := iter.Config().BorrowIterator([]byte(str))
|
||||
defer iter.Config().ReturnIterator(newIter)
|
||||
newIter := iter.Pool().BorrowIterator([]byte(str))
|
||||
defer iter.Pool().ReturnIterator(newIter)
|
||||
*((*float32)(ptr)) = newIter.ReadFloat32()
|
||||
if newIter.Error != nil {
|
||||
iter.Error = newIter.Error
|
||||
@ -244,8 +244,8 @@ func (decoder *fuzzyFloat64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.It
|
||||
*((*float64)(ptr)) = iter.ReadFloat64()
|
||||
case jsoniter.String:
|
||||
str = iter.ReadString()
|
||||
newIter := iter.Config().BorrowIterator([]byte(str))
|
||||
defer iter.Config().ReturnIterator(newIter)
|
||||
newIter := iter.Pool().BorrowIterator([]byte(str))
|
||||
defer iter.Pool().ReturnIterator(newIter)
|
||||
*((*float64)(ptr)) = newIter.ReadFloat64()
|
||||
if newIter.Error != nil {
|
||||
iter.Error = newIter.Error
|
||||
|
@ -1,14 +1,3 @@
|
||||
// Package jsoniter implements encoding and decoding of JSON as defined in
|
||||
// RFC 4627 and provides interfaces with identical syntax of standard lib encoding/json.
|
||||
// Converting from encoding/json to jsoniter is no more than replacing the package with jsoniter
|
||||
// and variable type declarations (if any).
|
||||
// jsoniter interfaces gives 100% compatibility with code using standard lib.
|
||||
//
|
||||
// "JSON and Go"
|
||||
// (https://golang.org/doc/articles/json_and_go.html)
|
||||
// gives a description of how Marshal/Unmarshal operate
|
||||
// between arbitrary or predefined json objects and bytes,
|
||||
// and it applies to jsoniter.Marshal/Unmarshal as well.
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
@ -96,7 +85,7 @@ func (adapter *Decoder) Buffered() io.Reader {
|
||||
func (decoder *Decoder) UseNumber() {
|
||||
origCfg := decoder.iter.cfg.configBeforeFrozen
|
||||
origCfg.UseNumber = true
|
||||
decoder.iter.cfg = origCfg.Froze()
|
||||
decoder.iter.cfg = origCfg.Froze().(*frozenConfig)
|
||||
}
|
||||
|
||||
func NewEncoder(writer io.Writer) *Encoder {
|
||||
@ -119,6 +108,6 @@ func (adapter *Encoder) SetIndent(prefix, indent string) {
|
||||
|
||||
func (adapter *Encoder) SetEscapeHTML(escapeHtml bool) {
|
||||
config := adapter.stream.cfg.configBeforeFrozen
|
||||
config.EscapeHtml = escapeHtml
|
||||
adapter.stream.cfg = config.Froze()
|
||||
config.EscapeHTML = escapeHtml
|
||||
adapter.stream.cfg = config.Froze().(*frozenConfig)
|
||||
}
|
||||
|
@ -9,10 +9,12 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Config customize how the API should behave.
|
||||
// The API is created from Config by Froze.
|
||||
type Config struct {
|
||||
IndentionStep int
|
||||
MarshalFloatWith6Digits bool
|
||||
EscapeHtml bool
|
||||
EscapeHTML bool
|
||||
SortMapKeys bool
|
||||
UseNumber bool
|
||||
}
|
||||
@ -28,7 +30,11 @@ type frozenConfig struct {
|
||||
iteratorPool chan *Iterator
|
||||
}
|
||||
|
||||
type Api interface {
|
||||
// API the public interface of this package.
|
||||
// Primary Marshal and Unmarshal.
|
||||
type API interface {
|
||||
IteratorPool
|
||||
StreamPool
|
||||
MarshalToString(v interface{}) (string, error)
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
|
||||
@ -39,22 +45,25 @@ type Api interface {
|
||||
NewDecoder(reader io.Reader) *Decoder
|
||||
}
|
||||
|
||||
// ConfigDefault the default API
|
||||
var ConfigDefault = Config{
|
||||
EscapeHtml: true,
|
||||
EscapeHTML: true,
|
||||
}.Froze()
|
||||
|
||||
// Trying to be 100% compatible with standard library behavior
|
||||
// ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior
|
||||
var ConfigCompatibleWithStandardLibrary = Config{
|
||||
EscapeHtml: true,
|
||||
EscapeHTML: true,
|
||||
SortMapKeys: true,
|
||||
}.Froze()
|
||||
|
||||
// ConfigFastest marshals float with only 6 digits precision
|
||||
var ConfigFastest = Config{
|
||||
EscapeHtml: false,
|
||||
EscapeHTML: false,
|
||||
MarshalFloatWith6Digits: true,
|
||||
}.Froze()
|
||||
|
||||
func (cfg Config) Froze() *frozenConfig {
|
||||
// Froze forge API from config
|
||||
func (cfg Config) Froze() API {
|
||||
// TODO: cache frozen config
|
||||
frozenConfig := &frozenConfig{
|
||||
sortMapKeys: cfg.SortMapKeys,
|
||||
@ -67,8 +76,8 @@ func (cfg Config) Froze() *frozenConfig {
|
||||
if cfg.MarshalFloatWith6Digits {
|
||||
frozenConfig.marshalFloatWith6Digits()
|
||||
}
|
||||
if cfg.EscapeHtml {
|
||||
frozenConfig.escapeHtml()
|
||||
if cfg.EscapeHTML {
|
||||
frozenConfig.escapeHTML()
|
||||
}
|
||||
if cfg.UseNumber {
|
||||
frozenConfig.useNumber()
|
||||
@ -145,7 +154,7 @@ func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return *((*string)(ptr)) == ""
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) escapeHtml() {
|
||||
func (cfg *frozenConfig) escapeHTML() {
|
||||
cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &htmlEscapedStringEncoder{})
|
||||
}
|
||||
|
||||
@ -189,18 +198,16 @@ func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
|
||||
return cache[cacheKey]
|
||||
}
|
||||
|
||||
// cleanDecoders cleans decoders registered or cached
|
||||
func (cfg *frozenConfig) cleanDecoders() {
|
||||
typeDecoders = map[string]ValDecoder{}
|
||||
fieldDecoders = map[string]ValDecoder{}
|
||||
*cfg = *cfg.configBeforeFrozen.Froze()
|
||||
*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
|
||||
}
|
||||
|
||||
// cleanEncoders cleans encoders registered or cached
|
||||
func (cfg *frozenConfig) cleanEncoders() {
|
||||
typeEncoders = map[string]ValEncoder{}
|
||||
fieldEncoders = map[string]ValEncoder{}
|
||||
*cfg = *cfg.configBeforeFrozen.Froze()
|
||||
*cfg = *(cfg.configBeforeFrozen.Froze().(*frozenConfig))
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {
|
||||
|
@ -1,9 +1,3 @@
|
||||
//
|
||||
// Besides, jsoniter.Iterator provides a different set of interfaces
|
||||
// iterating given bytes/string/reader
|
||||
// and yielding parsed elements one by one.
|
||||
// This set of interfaces reads input as required and gives
|
||||
// better performance.
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
@ -11,15 +5,23 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// ValueType the type for JSON element
|
||||
type ValueType int
|
||||
|
||||
const (
|
||||
// Invalid invalid JSON element
|
||||
Invalid ValueType = iota
|
||||
// String JSON element "string"
|
||||
String
|
||||
// Number JSON element 100 or 0.10
|
||||
Number
|
||||
// Nil JSON element null
|
||||
Nil
|
||||
// Bool JSON element true or false
|
||||
Bool
|
||||
// Array JSON element []
|
||||
Array
|
||||
// Object JSON element {}
|
||||
Object
|
||||
)
|
||||
|
||||
@ -63,7 +65,8 @@ func init() {
|
||||
valueTypes['{'] = Object
|
||||
}
|
||||
|
||||
// Iterator is a fast and flexible JSON parser
|
||||
// Iterator is a io.Reader like object, with JSON specific read functions.
|
||||
// Error is not returned as return value, but stored as Error member on this iterator instance.
|
||||
type Iterator struct {
|
||||
cfg *frozenConfig
|
||||
reader io.Reader
|
||||
@ -75,10 +78,10 @@ type Iterator struct {
|
||||
Error error
|
||||
}
|
||||
|
||||
// Create creates an empty Iterator instance
|
||||
func NewIterator(cfg *frozenConfig) *Iterator {
|
||||
// NewIterator creates an empty Iterator instance
|
||||
func NewIterator(cfg API) *Iterator {
|
||||
return &Iterator{
|
||||
cfg: cfg,
|
||||
cfg: cfg.(*frozenConfig),
|
||||
reader: nil,
|
||||
buf: nil,
|
||||
head: 0,
|
||||
@ -86,10 +89,10 @@ func NewIterator(cfg *frozenConfig) *Iterator {
|
||||
}
|
||||
}
|
||||
|
||||
// Parse parses a json buffer in io.Reader into an Iterator instance
|
||||
func Parse(cfg *frozenConfig, reader io.Reader, bufSize int) *Iterator {
|
||||
// Parse creates an Iterator instance from io.Reader
|
||||
func Parse(cfg API, reader io.Reader, bufSize int) *Iterator {
|
||||
return &Iterator{
|
||||
cfg: cfg,
|
||||
cfg: cfg.(*frozenConfig),
|
||||
reader: reader,
|
||||
buf: make([]byte, bufSize),
|
||||
head: 0,
|
||||
@ -97,10 +100,10 @@ func Parse(cfg *frozenConfig, reader io.Reader, bufSize int) *Iterator {
|
||||
}
|
||||
}
|
||||
|
||||
// ParseBytes parses a json byte slice into an Iterator instance
|
||||
func ParseBytes(cfg *frozenConfig, input []byte) *Iterator {
|
||||
// ParseBytes creates an Iterator instance from byte array
|
||||
func ParseBytes(cfg API, input []byte) *Iterator {
|
||||
return &Iterator{
|
||||
cfg: cfg,
|
||||
cfg: cfg.(*frozenConfig),
|
||||
reader: nil,
|
||||
buf: input,
|
||||
head: 0,
|
||||
@ -108,16 +111,17 @@ func ParseBytes(cfg *frozenConfig, input []byte) *Iterator {
|
||||
}
|
||||
}
|
||||
|
||||
// ParseString parses a json string into an Iterator instance
|
||||
func ParseString(cfg *frozenConfig, input string) *Iterator {
|
||||
// ParseString creates an Iterator instance from string
|
||||
func ParseString(cfg API, input string) *Iterator {
|
||||
return ParseBytes(cfg, []byte(input))
|
||||
}
|
||||
|
||||
func (iter *Iterator) Config() *frozenConfig {
|
||||
// Pool returns a pool can provide more iterator with same configuration
|
||||
func (iter *Iterator) Pool() IteratorPool {
|
||||
return iter.cfg
|
||||
}
|
||||
|
||||
// Reset can reset an Iterator instance for another json buffer in io.Reader
|
||||
// Reset reuse iterator instance by specifying another reader
|
||||
func (iter *Iterator) Reset(reader io.Reader) *Iterator {
|
||||
iter.reader = reader
|
||||
iter.head = 0
|
||||
@ -125,7 +129,7 @@ func (iter *Iterator) Reset(reader io.Reader) *Iterator {
|
||||
return iter
|
||||
}
|
||||
|
||||
// ResetBytes can reset an Iterator instance for another json byte slice
|
||||
// ResetBytes reuse iterator instance by specifying another byte array as input
|
||||
func (iter *Iterator) ResetBytes(input []byte) *Iterator {
|
||||
iter.reader = nil
|
||||
iter.buf = input
|
||||
@ -134,7 +138,7 @@ func (iter *Iterator) ResetBytes(input []byte) *Iterator {
|
||||
return iter
|
||||
}
|
||||
|
||||
// WhatIsNext gets ValueType of relatively next json object
|
||||
// WhatIsNext gets ValueType of relatively next json element
|
||||
func (iter *Iterator) WhatIsNext() ValueType {
|
||||
valueType := valueTypes[iter.nextToken()]
|
||||
iter.unreadByte()
|
||||
@ -184,6 +188,7 @@ func (iter *Iterator) nextToken() byte {
|
||||
}
|
||||
}
|
||||
|
||||
// ReportError record a error in iterator instance with current position.
|
||||
func (iter *Iterator) ReportError(operation string, msg string) {
|
||||
if iter.Error != nil {
|
||||
if iter.Error != io.EOF {
|
||||
@ -198,7 +203,7 @@ func (iter *Iterator) ReportError(operation string, msg string) {
|
||||
string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
|
||||
}
|
||||
|
||||
// CurrentBuffer gets current buffer as string
|
||||
// CurrentBuffer gets current buffer as string for debugging purpose
|
||||
func (iter *Iterator) CurrentBuffer() string {
|
||||
peekStart := iter.head - 10
|
||||
if peekStart < 0 {
|
||||
@ -261,6 +266,7 @@ func (iter *Iterator) unreadByte() {
|
||||
return
|
||||
}
|
||||
|
||||
// Read read the next JSON element as generic interface{}.
|
||||
func (iter *Iterator) Read() interface{} {
|
||||
valueType := iter.WhatIsNext()
|
||||
switch valueType {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package jsoniter
|
||||
|
||||
// ReadArray read array element, tells if the array has more element to read.
|
||||
func (iter *Iterator) ReadArray() (ret bool) {
|
||||
c := iter.nextToken()
|
||||
switch c {
|
||||
@ -23,6 +24,7 @@ func (iter *Iterator) ReadArray() (ret bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadArrayCB read array with callback
|
||||
func (iter *Iterator) ReadArrayCB(callback func(*Iterator) bool) (ret bool) {
|
||||
c := iter.nextToken()
|
||||
if c == '[' {
|
||||
|
@ -30,6 +30,7 @@ func init() {
|
||||
floatDigits['.'] = dotInNumber
|
||||
}
|
||||
|
||||
// ReadBigFloat read big.Float
|
||||
func (iter *Iterator) ReadBigFloat() (ret *big.Float) {
|
||||
str := iter.readNumberAsString()
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
@ -47,6 +48,7 @@ func (iter *Iterator) ReadBigFloat() (ret *big.Float) {
|
||||
return val
|
||||
}
|
||||
|
||||
// ReadBigInt read big.Int
|
||||
func (iter *Iterator) ReadBigInt() (ret *big.Int) {
|
||||
str := iter.readNumberAsString()
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
@ -62,14 +64,14 @@ func (iter *Iterator) ReadBigInt() (ret *big.Int) {
|
||||
return ret
|
||||
}
|
||||
|
||||
//ReadFloat32 read float32
|
||||
func (iter *Iterator) ReadFloat32() (ret float32) {
|
||||
c := iter.nextToken()
|
||||
if c == '-' {
|
||||
return -iter.readPositiveFloat32()
|
||||
} else {
|
||||
iter.unreadByte()
|
||||
return iter.readPositiveFloat32()
|
||||
}
|
||||
iter.unreadByte()
|
||||
return iter.readPositiveFloat32()
|
||||
}
|
||||
|
||||
func (iter *Iterator) readPositiveFloat32() (ret float32) {
|
||||
@ -165,14 +167,14 @@ func (iter *Iterator) readFloat32SlowPath() (ret float32) {
|
||||
return float32(val)
|
||||
}
|
||||
|
||||
// ReadFloat64 read float64
|
||||
func (iter *Iterator) ReadFloat64() (ret float64) {
|
||||
c := iter.nextToken()
|
||||
if c == '-' {
|
||||
return -iter.readPositiveFloat64()
|
||||
} else {
|
||||
iter.unreadByte()
|
||||
return iter.readPositiveFloat64()
|
||||
}
|
||||
iter.unreadByte()
|
||||
return iter.readPositiveFloat64()
|
||||
}
|
||||
|
||||
func (iter *Iterator) readPositiveFloat64() (ret float64) {
|
||||
|
@ -20,14 +20,17 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadUint read uint
|
||||
func (iter *Iterator) ReadUint() uint {
|
||||
return uint(iter.ReadUint64())
|
||||
}
|
||||
|
||||
// ReadInt read int
|
||||
func (iter *Iterator) ReadInt() int {
|
||||
return int(iter.ReadInt64())
|
||||
}
|
||||
|
||||
// ReadInt8 read int8
|
||||
func (iter *Iterator) ReadInt8() (ret int8) {
|
||||
c := iter.nextToken()
|
||||
if c == '-' {
|
||||
@ -37,16 +40,16 @@ func (iter *Iterator) ReadInt8() (ret int8) {
|
||||
return
|
||||
}
|
||||
return -int8(val)
|
||||
} else {
|
||||
val := iter.readUint32(c)
|
||||
if val > math.MaxInt8 {
|
||||
iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10))
|
||||
return
|
||||
}
|
||||
return int8(val)
|
||||
}
|
||||
val := iter.readUint32(c)
|
||||
if val > math.MaxInt8 {
|
||||
iter.ReportError("ReadInt8", "overflow: "+strconv.FormatInt(int64(val), 10))
|
||||
return
|
||||
}
|
||||
return int8(val)
|
||||
}
|
||||
|
||||
// ReadUint8 read uint8
|
||||
func (iter *Iterator) ReadUint8() (ret uint8) {
|
||||
val := iter.readUint32(iter.nextToken())
|
||||
if val > math.MaxUint8 {
|
||||
@ -56,6 +59,7 @@ func (iter *Iterator) ReadUint8() (ret uint8) {
|
||||
return uint8(val)
|
||||
}
|
||||
|
||||
// ReadInt16 read int16
|
||||
func (iter *Iterator) ReadInt16() (ret int16) {
|
||||
c := iter.nextToken()
|
||||
if c == '-' {
|
||||
@ -65,16 +69,16 @@ func (iter *Iterator) ReadInt16() (ret int16) {
|
||||
return
|
||||
}
|
||||
return -int16(val)
|
||||
} else {
|
||||
val := iter.readUint32(c)
|
||||
if val > math.MaxInt16 {
|
||||
iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10))
|
||||
return
|
||||
}
|
||||
return int16(val)
|
||||
}
|
||||
val := iter.readUint32(c)
|
||||
if val > math.MaxInt16 {
|
||||
iter.ReportError("ReadInt16", "overflow: "+strconv.FormatInt(int64(val), 10))
|
||||
return
|
||||
}
|
||||
return int16(val)
|
||||
}
|
||||
|
||||
// ReadUint16 read uint16
|
||||
func (iter *Iterator) ReadUint16() (ret uint16) {
|
||||
val := iter.readUint32(iter.nextToken())
|
||||
if val > math.MaxUint16 {
|
||||
@ -84,6 +88,7 @@ func (iter *Iterator) ReadUint16() (ret uint16) {
|
||||
return uint16(val)
|
||||
}
|
||||
|
||||
// ReadInt32 read int32
|
||||
func (iter *Iterator) ReadInt32() (ret int32) {
|
||||
c := iter.nextToken()
|
||||
if c == '-' {
|
||||
@ -93,16 +98,16 @@ func (iter *Iterator) ReadInt32() (ret int32) {
|
||||
return
|
||||
}
|
||||
return -int32(val)
|
||||
} else {
|
||||
val := iter.readUint32(c)
|
||||
if val > math.MaxInt32 {
|
||||
iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10))
|
||||
return
|
||||
}
|
||||
return int32(val)
|
||||
}
|
||||
val := iter.readUint32(c)
|
||||
if val > math.MaxInt32 {
|
||||
iter.ReportError("ReadInt32", "overflow: "+strconv.FormatInt(int64(val), 10))
|
||||
return
|
||||
}
|
||||
return int32(val)
|
||||
}
|
||||
|
||||
// ReadUint32 read uint32
|
||||
func (iter *Iterator) ReadUint32() (ret uint32) {
|
||||
return iter.readUint32(iter.nextToken())
|
||||
}
|
||||
@ -182,10 +187,9 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
|
||||
if value2 < value {
|
||||
iter.ReportError("readUint32", "overflow")
|
||||
return
|
||||
} else {
|
||||
value = value2
|
||||
continue
|
||||
}
|
||||
value = value2
|
||||
continue
|
||||
}
|
||||
value = (value << 3) + (value << 1) + uint32(ind)
|
||||
}
|
||||
@ -195,6 +199,7 @@ func (iter *Iterator) readUint32(c byte) (ret uint32) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadInt64 read int64
|
||||
func (iter *Iterator) ReadInt64() (ret int64) {
|
||||
c := iter.nextToken()
|
||||
if c == '-' {
|
||||
@ -204,16 +209,16 @@ func (iter *Iterator) ReadInt64() (ret int64) {
|
||||
return
|
||||
}
|
||||
return -int64(val)
|
||||
} else {
|
||||
val := iter.readUint64(c)
|
||||
if val > math.MaxInt64 {
|
||||
iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10))
|
||||
return
|
||||
}
|
||||
return int64(val)
|
||||
}
|
||||
val := iter.readUint64(c)
|
||||
if val > math.MaxInt64 {
|
||||
iter.ReportError("ReadInt64", "overflow: "+strconv.FormatUint(uint64(val), 10))
|
||||
return
|
||||
}
|
||||
return int64(val)
|
||||
}
|
||||
|
||||
// ReadUint64 read uint64
|
||||
func (iter *Iterator) ReadUint64() uint64 {
|
||||
return iter.readUint64(iter.nextToken())
|
||||
}
|
||||
@ -240,10 +245,9 @@ func (iter *Iterator) readUint64(c byte) (ret uint64) {
|
||||
if value2 < value {
|
||||
iter.ReportError("readUint64", "overflow")
|
||||
return
|
||||
} else {
|
||||
value = value2
|
||||
continue
|
||||
}
|
||||
value = value2
|
||||
continue
|
||||
}
|
||||
value = (value << 3) + (value << 1) + uint64(ind)
|
||||
}
|
||||
|
@ -6,6 +6,9 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ReadObject read one field from object.
|
||||
// If object ended, returns empty string.
|
||||
// Otherwise, returns the field name.
|
||||
func (iter *Iterator) ReadObject() (ret string) {
|
||||
c := iter.nextToken()
|
||||
switch c {
|
||||
@ -74,6 +77,7 @@ func calcHash(str string) int32 {
|
||||
return int32(hash)
|
||||
}
|
||||
|
||||
// ReadObjectCB read object with callback, the key is ascii only and field name not copied
|
||||
func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
|
||||
c := iter.nextToken()
|
||||
if c == '{' {
|
||||
@ -106,6 +110,7 @@ func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ReadMapCB read map with callback, the key can be any string
|
||||
func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
|
||||
c := iter.nextToken()
|
||||
if c == '{' {
|
||||
|
@ -29,6 +29,8 @@ func (iter *Iterator) ReadBool() (ret bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// SkipAndReturnBytes skip next JSON element, and return its content as []byte.
|
||||
// The []byte can be kept, it is a copy of data.
|
||||
func (iter *Iterator) SkipAndReturnBytes() []byte {
|
||||
iter.startCapture(iter.head)
|
||||
iter.Skip()
|
||||
@ -58,10 +60,9 @@ func (iter *Iterator) stopCapture() []byte {
|
||||
iter.captured = nil
|
||||
if len(captured) == 0 {
|
||||
return remaining
|
||||
} else {
|
||||
captured = append(captured, remaining...)
|
||||
return captured
|
||||
}
|
||||
captured = append(captured, remaining...)
|
||||
return captured
|
||||
}
|
||||
|
||||
// Skip skips a json object and positions to relatively the next json object
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"unicode/utf16"
|
||||
)
|
||||
|
||||
// ReadString read string from iterator
|
||||
func (iter *Iterator) ReadString() (ret string) {
|
||||
c := iter.nextToken()
|
||||
if c == '"' {
|
||||
@ -96,6 +97,8 @@ func (iter *Iterator) readStringSlowPath() (ret string) {
|
||||
return
|
||||
}
|
||||
|
||||
// ReadStringAsSlice read string from iterator without copying into string form.
|
||||
// The []byte can not be kept, as it will change after next iterator call.
|
||||
func (iter *Iterator) ReadStringAsSlice() (ret []byte) {
|
||||
c := iter.nextToken()
|
||||
if c == '"' {
|
||||
|
@ -4,6 +4,18 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// IteratorPool a thread safe pool of iterators with same configuration
|
||||
type IteratorPool interface {
|
||||
BorrowIterator(data []byte) *Iterator
|
||||
ReturnIterator(iter *Iterator)
|
||||
}
|
||||
|
||||
// StreamPool a thread safe pool of streams with same configuration
|
||||
type StreamPool interface {
|
||||
BorrowStream(writer io.Writer) *Stream
|
||||
ReturnStream(stream *Stream)
|
||||
}
|
||||
|
||||
func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream {
|
||||
select {
|
||||
case stream := <-cfg.streamPool:
|
||||
|
@ -36,6 +36,7 @@ type checkIsEmpty interface {
|
||||
IsEmpty(ptr unsafe.Pointer) bool
|
||||
}
|
||||
|
||||
// WriteToStream the default implementation for TypeEncoder method EncodeInterface
|
||||
func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) {
|
||||
e := (*emptyInterface)(unsafe.Pointer(&val))
|
||||
if e.word == nil {
|
||||
@ -49,9 +50,6 @@ func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) {
|
||||
}
|
||||
}
|
||||
|
||||
type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator)
|
||||
type EncoderFunc func(ptr unsafe.Pointer, stream *Stream)
|
||||
|
||||
var jsonNumberType reflect.Type
|
||||
var jsonRawMessageType reflect.Type
|
||||
var jsoniterRawMessageType reflect.Type
|
||||
@ -132,9 +130,8 @@ func (encoder *optionalEncoder) EncodeInterface(val interface{}, stream *Stream)
|
||||
func (encoder *optionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
if *((*unsafe.Pointer)(ptr)) == nil {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type placeholderEncoder struct {
|
||||
@ -206,7 +203,7 @@ type nonEmptyInterface struct {
|
||||
word unsafe.Pointer
|
||||
}
|
||||
|
||||
// Read converts an Iterator instance into go interface, same as json.Unmarshal
|
||||
// ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
|
||||
func (iter *Iterator) ReadVal(obj interface{}) {
|
||||
typ := reflect.TypeOf(obj)
|
||||
cacheKey := typ.Elem()
|
||||
@ -219,6 +216,7 @@ func (iter *Iterator) ReadVal(obj interface{}) {
|
||||
decoder.Decode(e.word, iter)
|
||||
}
|
||||
|
||||
// WriteVal copy the go interface into underlying JSON, same as json.Marshal
|
||||
func (stream *Stream) WriteVal(val interface{}) {
|
||||
if nil == val {
|
||||
stream.WriteNil()
|
||||
@ -393,9 +391,8 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
|
||||
case reflect.Interface:
|
||||
if typ.NumMethod() == 0 {
|
||||
return &emptyInterfaceCodec{}, nil
|
||||
} else {
|
||||
return &nonEmptyInterfaceCodec{}, nil
|
||||
}
|
||||
return &nonEmptyInterfaceCodec{}, nil
|
||||
case reflect.Struct:
|
||||
return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(cfg, typ))
|
||||
case reflect.Array:
|
||||
@ -517,9 +514,8 @@ func createCheckIsEmpty(typ reflect.Type) (checkIsEmpty, error) {
|
||||
case reflect.Interface:
|
||||
if typ.NumMethod() == 0 {
|
||||
return &emptyInterfaceCodec{}, nil
|
||||
} else {
|
||||
return &nonEmptyInterfaceCodec{}, nil
|
||||
}
|
||||
return &nonEmptyInterfaceCodec{}, nil
|
||||
case reflect.Struct:
|
||||
return &structEncoder{}, nil
|
||||
case reflect.Array:
|
||||
@ -617,9 +613,8 @@ func createEncoderOfSimpleType(cfg *frozenConfig, typ reflect.Type) (ValEncoder,
|
||||
case reflect.Interface:
|
||||
if typ.NumMethod() == 0 {
|
||||
return &emptyInterfaceCodec{}, nil
|
||||
} else {
|
||||
return &nonEmptyInterfaceCodec{}, nil
|
||||
}
|
||||
return &nonEmptyInterfaceCodec{}, nil
|
||||
case reflect.Struct:
|
||||
return prefix(fmt.Sprintf("[%s]", typeName)).addToEncoder(encoderOfStruct(cfg, typ))
|
||||
case reflect.Array:
|
||||
@ -679,7 +674,6 @@ func encoderOfMap(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
|
||||
mapInterface := reflect.New(typ).Elem().Interface()
|
||||
if cfg.sortMapKeys {
|
||||
return &sortKeysMapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
|
||||
} else {
|
||||
return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
|
||||
}
|
||||
return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
|
||||
}
|
||||
|
@ -110,6 +110,11 @@ func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
||||
return encoder.isEmptyFunc(ptr)
|
||||
}
|
||||
|
||||
// DecoderFunc the function form of TypeDecoder
|
||||
type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator)
|
||||
// EncoderFunc the function form of TypeEncoder
|
||||
type EncoderFunc func(ptr unsafe.Pointer, stream *Stream)
|
||||
|
||||
// RegisterTypeDecoderFunc register TypeDecoder for a type with function
|
||||
func RegisterTypeDecoderFunc(typ string, fun DecoderFunc) {
|
||||
typeDecoders[typ] = &funcDecoder{fun}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"io"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@ -71,7 +71,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
||||
}
|
||||
}
|
||||
return &threeFieldsStructDecoder{typ,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
|
||||
case 4:
|
||||
var fieldName1 int32
|
||||
var fieldName2 int32
|
||||
@ -103,8 +103,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
||||
}
|
||||
}
|
||||
return &fourFieldsStructDecoder{typ,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4}, nil
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4}, nil
|
||||
case 5:
|
||||
var fieldName1 int32
|
||||
var fieldName2 int32
|
||||
@ -141,8 +141,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
||||
}
|
||||
}
|
||||
return &fiveFieldsStructDecoder{typ,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
|
||||
case 6:
|
||||
var fieldName1 int32
|
||||
var fieldName2 int32
|
||||
@ -184,8 +184,8 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
||||
}
|
||||
}
|
||||
return &sixFieldsStructDecoder{typ,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
|
||||
case 7:
|
||||
var fieldName1 int32
|
||||
var fieldName2 int32
|
||||
@ -232,9 +232,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
||||
}
|
||||
}
|
||||
return &sevenFieldsStructDecoder{typ,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
||||
fieldName7, fieldDecoder7}, nil
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
||||
fieldName7, fieldDecoder7}, nil
|
||||
case 8:
|
||||
var fieldName1 int32
|
||||
var fieldName2 int32
|
||||
@ -286,9 +286,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
||||
}
|
||||
}
|
||||
return &eightFieldsStructDecoder{typ,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
||||
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
||||
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
|
||||
case 9:
|
||||
var fieldName1 int32
|
||||
var fieldName2 int32
|
||||
@ -345,9 +345,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
||||
}
|
||||
}
|
||||
return &nineFieldsStructDecoder{typ,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
||||
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
||||
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
|
||||
case 10:
|
||||
var fieldName1 int32
|
||||
var fieldName2 int32
|
||||
@ -409,15 +409,14 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
|
||||
}
|
||||
}
|
||||
return &tenFieldsStructDecoder{typ,
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
||||
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
|
||||
fieldName10, fieldDecoder10}, nil
|
||||
fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
|
||||
fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
|
||||
fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
|
||||
fieldName10, fieldDecoder10}, nil
|
||||
}
|
||||
return &generalStructDecoder{typ, fields}, nil
|
||||
}
|
||||
|
||||
|
||||
type generalStructDecoder struct {
|
||||
typ reflect.Type
|
||||
fields map[string]*structFieldDecoder
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Stream is a writer like object, with JSON specific write functions.
|
||||
// Stream is a io.Writer like object, with JSON specific write functions.
|
||||
// Error is not returned as return value, but stored as Error member on this stream instance.
|
||||
type Stream struct {
|
||||
cfg *frozenConfig
|
||||
@ -19,9 +19,9 @@ type Stream struct {
|
||||
// cfg can be jsoniter.ConfigDefault.
|
||||
// out can be nil if write to internal buffer.
|
||||
// bufSize is the initial size for the internal buffer in bytes.
|
||||
func NewStream(cfg *frozenConfig, out io.Writer, bufSize int) *Stream {
|
||||
func NewStream(cfg API, out io.Writer, bufSize int) *Stream {
|
||||
return &Stream{
|
||||
cfg: cfg,
|
||||
cfg: cfg.(*frozenConfig),
|
||||
out: out,
|
||||
buf: make([]byte, bufSize),
|
||||
n: 0,
|
||||
@ -30,6 +30,11 @@ func NewStream(cfg *frozenConfig, out io.Writer, bufSize int) *Stream {
|
||||
}
|
||||
}
|
||||
|
||||
// Pool returns a pool can provide more stream with same configuration
|
||||
func (stream *Stream) Pool() StreamPool {
|
||||
return stream.cfg
|
||||
}
|
||||
|
||||
// Reset reuse this stream instance by assign a new writer
|
||||
func (stream *Stream) Reset(out io.Writer) {
|
||||
stream.out = out
|
||||
@ -196,7 +201,6 @@ func (stream *Stream) growAtLeast(minimal int) {
|
||||
stream.buf = newBuf
|
||||
}
|
||||
|
||||
|
||||
// WriteRaw write string out without quotes, just like []byte
|
||||
func (stream *Stream) WriteRaw(s string) {
|
||||
stream.ensure(len(s))
|
||||
|
18
jsoniter.go
Normal file
18
jsoniter.go
Normal file
@ -0,0 +1,18 @@
|
||||
// Package jsoniter implements encoding and decoding of JSON as defined in
|
||||
// RFC 4627 and provides interfaces with identical syntax of standard lib encoding/json.
|
||||
// Converting from encoding/json to jsoniter is no more than replacing the package with jsoniter
|
||||
// and variable type declarations (if any).
|
||||
// jsoniter interfaces gives 100% compatibility with code using standard lib.
|
||||
//
|
||||
// "JSON and Go"
|
||||
// (https://golang.org/doc/articles/json_and_go.html)
|
||||
// gives a description of how Marshal/Unmarshal operate
|
||||
// between arbitrary or predefined json objects and bytes,
|
||||
// and it applies to jsoniter.Marshal/Unmarshal as well.
|
||||
//
|
||||
// Besides, jsoniter.Iterator provides a different set of interfaces
|
||||
// iterating given bytes/string/reader
|
||||
// and yielding parsed elements one by one.
|
||||
// This set of interfaces reads input as required and gives
|
||||
// better performance.
|
||||
package jsoniter
|
@ -26,7 +26,7 @@ func Test_new_encoder(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_string_encode_with_std_without_html_escape(t *testing.T) {
|
||||
api := Config{EscapeHtml: false}.Froze()
|
||||
api := Config{EscapeHTML: false}.Froze()
|
||||
should := require.New(t)
|
||||
for i := 0; i < utf8.RuneSelf; i++ {
|
||||
input := string([]byte{byte(i)})
|
||||
|
@ -7,25 +7,25 @@ import (
|
||||
)
|
||||
|
||||
var stringConvertMap = map[string]string{
|
||||
"null": "",
|
||||
"321.1": "321.1",
|
||||
`"1.1"`: "1.1",
|
||||
`"-123.1"`: "-123.1",
|
||||
"0.0": "0.0",
|
||||
"0": "0",
|
||||
`"0"`: "0",
|
||||
`"0.0"`: "0.0",
|
||||
`"00.0"`: "00.0",
|
||||
"true": "true",
|
||||
"false": "false",
|
||||
`"true"`: "true",
|
||||
`"false"`: "false",
|
||||
`"true123"`: "true123",
|
||||
`"+1"`: "+1",
|
||||
"[]": "[]",
|
||||
"[1,2]": "[1,2]",
|
||||
"{}": "{}",
|
||||
"{1,2}": "{1,2}",
|
||||
"null": "",
|
||||
"321.1": "321.1",
|
||||
`"1.1"`: "1.1",
|
||||
`"-123.1"`: "-123.1",
|
||||
"0.0": "0.0",
|
||||
"0": "0",
|
||||
`"0"`: "0",
|
||||
`"0.0"`: "0.0",
|
||||
`"00.0"`: "00.0",
|
||||
"true": "true",
|
||||
"false": "false",
|
||||
`"true"`: "true",
|
||||
`"false"`: "false",
|
||||
`"true123"`: "true123",
|
||||
`"+1"`: "+1",
|
||||
"[]": "[]",
|
||||
"[1,2]": "[1,2]",
|
||||
"{}": "{}",
|
||||
"{1,2}": "{1,2}",
|
||||
`{"a":1, "stream":true}`: `{"a":1, "stream":true}`,
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ func Test_customize_type_decoder(t *testing.T) {
|
||||
}
|
||||
*((*time.Time)(ptr)) = t
|
||||
})
|
||||
defer ConfigDefault.cleanDecoders()
|
||||
defer ConfigDefault.(*frozenConfig).cleanDecoders()
|
||||
val := time.Time{}
|
||||
err := Unmarshal([]byte(`"2016-12-05 08:43:28"`), &val)
|
||||
if err != nil {
|
||||
@ -36,7 +36,7 @@ func Test_customize_type_encoder(t *testing.T) {
|
||||
t := *((*time.Time)(ptr))
|
||||
stream.WriteString(t.UTC().Format("2006-01-02 15:04:05"))
|
||||
}, nil)
|
||||
defer ConfigDefault.cleanEncoders()
|
||||
defer ConfigDefault.(*frozenConfig).cleanEncoders()
|
||||
val := time.Unix(0, 0)
|
||||
str, err := MarshalToString(val)
|
||||
should.Nil(err)
|
||||
@ -44,13 +44,13 @@ func Test_customize_type_encoder(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_customize_byte_array_encoder(t *testing.T) {
|
||||
ConfigDefault.cleanEncoders()
|
||||
ConfigDefault.(*frozenConfig).cleanEncoders()
|
||||
should := require.New(t)
|
||||
RegisterTypeEncoderFunc("[]uint8", func(ptr unsafe.Pointer, stream *Stream) {
|
||||
t := *((*[]byte)(ptr))
|
||||
stream.WriteString(string(t))
|
||||
}, nil)
|
||||
defer ConfigDefault.cleanEncoders()
|
||||
defer ConfigDefault.(*frozenConfig).cleanEncoders()
|
||||
val := []byte("abc")
|
||||
str, err := MarshalToString(val)
|
||||
should.Nil(err)
|
||||
@ -73,7 +73,7 @@ func Test_customize_field_decoder(t *testing.T) {
|
||||
RegisterFieldDecoderFunc("jsoniter.Tom", "field1", func(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
|
||||
})
|
||||
defer ConfigDefault.cleanDecoders()
|
||||
defer ConfigDefault.(*frozenConfig).cleanDecoders()
|
||||
tom := Tom{}
|
||||
err := Unmarshal([]byte(`{"field1": 100}`), &tom)
|
||||
if err != nil {
|
||||
@ -144,7 +144,7 @@ func Test_marshaler_and_encoder(t *testing.T) {
|
||||
type TestObject struct {
|
||||
Field *timeImplementedMarshaler
|
||||
}
|
||||
ConfigDefault.cleanEncoders()
|
||||
ConfigDefault.(*frozenConfig).cleanEncoders()
|
||||
should := require.New(t)
|
||||
RegisterTypeEncoderFunc("jsoniter.timeImplementedMarshaler", func(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteString("hello from encoder")
|
||||
@ -184,7 +184,7 @@ func Test_unmarshaler_and_decoder(t *testing.T) {
|
||||
Field *ObjectImplementedUnmarshaler
|
||||
Field2 string
|
||||
}
|
||||
ConfigDefault.cleanDecoders()
|
||||
ConfigDefault.(*frozenConfig).cleanDecoders()
|
||||
should := require.New(t)
|
||||
RegisterTypeDecoderFunc("jsoniter.ObjectImplementedUnmarshaler", func(ptr unsafe.Pointer, iter *Iterator) {
|
||||
*(*ObjectImplementedUnmarshaler)(ptr) = 10
|
||||
|
@ -141,8 +141,8 @@ func Test_encode_object_contain_non_empty_interface(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_nil_non_empty_interface(t *testing.T) {
|
||||
ConfigDefault.cleanEncoders()
|
||||
ConfigDefault.cleanDecoders()
|
||||
ConfigDefault.(*frozenConfig).cleanEncoders()
|
||||
ConfigDefault.(*frozenConfig).cleanDecoders()
|
||||
type TestObject struct {
|
||||
Field []MyInterface
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ package jsoniter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/stretchr/testify/require"
|
||||
"io"
|
||||
"testing"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_read_by_one(t *testing.T) {
|
||||
|
@ -127,7 +127,7 @@ func Test_unicode(t *testing.T) {
|
||||
should := require.New(t)
|
||||
output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"})
|
||||
should.Equal(`{"a":"数字山谷"}`, output)
|
||||
output, _ = Config{EscapeHtml: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"})
|
||||
output, _ = Config{EscapeHTML: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"})
|
||||
should.Equal(`{"a":"数字山谷"}`, output)
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ func Test_unicode_and_escape(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_unsafe_unicode(t *testing.T) {
|
||||
ConfigDefault.cleanEncoders()
|
||||
ConfigDefault.(*frozenConfig).cleanEncoders()
|
||||
should := require.New(t)
|
||||
output, err := ConfigDefault.MarshalToString("he\u2029\u2028he")
|
||||
should.Nil(err)
|
||||
|
Loading…
x
Reference in New Issue
Block a user