jzon

package module
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 17, 2020 License: MIT Imports: 19 Imported by: 1

README

Go Report Card Build Status codecov

jzon

Why another jsoniter?

The code I write here is very similar to github.com/json-iterator/go, so you may ask why reinvent the wheel.

For sure that I benefit a lot from the jsoniter library, but i found some inconvenience for me to use it in some condition, for example:

  • the iterator methods ReadString accepts null, there is no method which accepts exactly string. I have to do some extra check before calling.
  • some behavior is not compatible with the standard library.
  • I want a chained streamer

On the other hand, I also want to learn how the jsoniter works, so there is this repo.

What's different from jsoniter?

Here are some of the differences:

  • the iterator methods accept the exact type, for example ReadString accepts only string, not null
  • the behavior is almost the same as the standard library (when an error returns, the behavior may differ from the standard library)
  • the error of the iterator is returned instead of being saved inside iterator
  • the decoder/encoder interface has additional options, like struct tag options

Some features of jsoniter are not implemented, and may be not implemented in the future neither. I choose only the ones I need to implement.

Compatibility with standard library

I tried implemented a version which is completely compatible with the standard library:

https://github.com/zerosnake0/jzon/tree/reflect

The benchmark shows that it's much faster than the standard library. However it is still much slower than the current version, which cannot be exactly the same as standard library (at least in my POV).

The major incompatibility is about the two following interfaces:

  • json.Marshaler
  • encoding.TextMarshaler

The method on pointer receiver may be called with an unaddressable value, for example:

type field struct {}

func (*field) MarshalJSON() ([]byte, error)

type st struct {
    F field
}

json.Marshal(st{}) // will not call field.MarshalJSON
jzon.Marshal(st{}) // will call field.MarshalJSON

So the user should be care when marshaling a value when method on pointer receiver is involved

You can check the tests for more detailed info about the difference

How to use

Standard library like
import "github.com/zerosnake0/jzon"

// Unmarshal
err := jzon.Unmarshal(b, &data)

// Marshal
b, err := jzon.Marshal(&data)
Iterator
iter := jzon.NewIterator()
defer jzon.ReturnIterator(iter)
iter.Reset(b)
jzon.ReadVal(&data)
Streamer
var w io.Writer

streamer := jzon.NewStreamer()
defer jzon.ReturnStreamer(streamer)
streamer.Reset(w)
streamer.Value(&data)
streamer.Flush()
Custom Decoder

see decoder_test.go

type testIntDecoder struct{}

func (*testIntDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error {
    ...
}

dec := NewDecoder(&DecoderOption{
    ValDecoders: map[reflect.Type]ValDecoder{
        reflect.TypeOf(int(0)): (*testIntDecoder)(nil),
    },
    CaseSensitive: true,
})

// standard library like
err := dec.Unmarshal(b, &data)

// iterator
iter := dec.NewIterator()
defer dec.ReturnIterator(iter)
Custom Encoder

see encoder_test.go

type testIntEncoder struct{}

func (*testIntEncoder) IsEmpty(ptr unsafe.Pointer) bool {
    ...
}

func (*testIntEncoder) Encode(ptr unsafe.Pointer, s *Streamer, opts *EncOpts) {
    ...
}

enc := NewEncoder(&EncoderOption{
    ValEncoders: map[reflect.Type]ValEncoder{
        reflect.TypeOf(int(0)): (*testIntEncoder)(nil),
    },
})

// standard library like
b, err := enc.Marshal(&data)

// streamer
streamer := enc.NewStreamer()
defer enc.ReturnStreamer(streamer)

Documentation

Overview

see encoding/json * - some additional comments may be added * - some code may be slightly modified

see encoding/json * - some additional comments may be added * - some code may be slightly modified

see encoding/json * - some additional comments may be added * - some code may be slightly modified

see encoding/json * - some additional comments may be added * - some code may be slightly modified

Index

Constants

This section is empty.

Variables

View Source
var DataRemainedError = errors.New("expecting EOF, but there is still data")

DataRemainedError

View Source
var (
	// default decoder is compatible with standard lib
	DefaultDecoder = NewDecoder(nil)
)
View Source
var (
	DefaultEncoder = NewEncoder(nil)
)
View Source
var EfaceLoopingError = errors.New("eface looping detected")

EfaceLoopingError

View Source
var FloatIsInfinity = errors.New("float is infinity")
View Source
var FloatIsNan = errors.New("float is NaN")
View Source
var IFaceError = errors.New("cannot unmarshal on empty iface")

IFaceError

View Source
var NilEmbeddedPointerError = errors.New("cannot unmarshal on nil pointer (unexported embedded)")

NilEmbeddedError

View Source
var NilPointerReceiverError = errors.New("the receiver is nil")

NilPointerReceiverError

View Source
var NoWriterAttachedError = errors.New("no writer attached")
View Source
var PointerReceiverError = errors.New("the receiver is not a pointer")

PointerReceiverError

Functions

func Marshal

func Marshal(o interface{}) ([]byte, error)

func ReturnIterator

func ReturnIterator(it *Iterator)

func ReturnStreamer

func ReturnStreamer(s *Streamer)

func Unmarshal

func Unmarshal(data []byte, o interface{}) error

func UnmarshalFromReader added in v0.0.4

func UnmarshalFromReader(r io.Reader, o interface{}) error

func Valid

func Valid(data []byte) bool

Types

type BadQuotedStringError

type BadQuotedStringError string

BadQuotedString

func (BadQuotedStringError) Error

func (e BadQuotedStringError) Error() string

type DecOpts

type DecOpts struct {
	MapKey bool
	Quoted bool
}

type DecodeError

type DecodeError struct {
	// contains filtered or unexported fields
}

func (*DecodeError) Error

func (e *DecodeError) Error() string

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

func NewDecoder

func NewDecoder(opt *DecoderOption) *Decoder

func (*Decoder) NewIterator

func (dec *Decoder) NewIterator() *Iterator

func (*Decoder) ReturnIterator

func (dec *Decoder) ReturnIterator(it *Iterator)

func (*Decoder) Unmarshal

func (dec *Decoder) Unmarshal(data []byte, obj interface{}) error

func (*Decoder) UnmarshalFromReader added in v0.0.3

func (dec *Decoder) UnmarshalFromReader(r io.Reader, obj interface{}) error

func (*Decoder) UnmarshalFromString

func (dec *Decoder) UnmarshalFromString(s string, obj interface{}) error

type DecoderOption

type DecoderOption struct {
	// custom value decoders
	ValDecoders map[reflect.Type]ValDecoder

	// if the object key is case sensitive
	// `false` by default
	CaseSensitive bool

	// the tag name for structures
	// `json` by default
	Tag string

	OnlyTaggedField bool

	UseNumber bool

	DisallowUnknownFields bool
}

type EncOpts

type EncOpts struct {
	Quoted bool
}

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

func NewEncoder

func NewEncoder(opt *EncoderOption) *Encoder

func (*Encoder) Marshal

func (enc *Encoder) Marshal(obj interface{}) ([]byte, error)

func (*Encoder) NewStreamer

func (enc *Encoder) NewStreamer() *Streamer

func (*Encoder) ReturnStreamer

func (enc *Encoder) ReturnStreamer(s *Streamer)

type EncoderOption

type EncoderOption struct {
	ValEncoders map[reflect.Type]ValEncoder

	EscapeHTML      bool
	Tag             string
	OnlyTaggedField bool
}

type IntOverflowError

type IntOverflowError struct {
	// contains filtered or unexported fields
}

IntOverflow

func (IntOverflowError) Error

func (e IntOverflowError) Error() string

type InvalidDigitError

type InvalidDigitError struct {
	// contains filtered or unexported fields
}

InvalidDigit

func (InvalidDigitError) Error

func (e InvalidDigitError) Error() string

type InvalidEscapeCharError

type InvalidEscapeCharError struct {
	// contains filtered or unexported fields
}

InvalidEscapeCharError

func (InvalidEscapeCharError) Error

func (e InvalidEscapeCharError) Error() string

type InvalidFloatError

type InvalidFloatError struct {
	// contains filtered or unexported fields
}

InvalidFloat

func (InvalidFloatError) Error

func (e InvalidFloatError) Error() string

type InvalidStringCharError

type InvalidStringCharError struct {
	// contains filtered or unexported fields
}

InvalidStringCharError

func (InvalidStringCharError) Error

func (e InvalidStringCharError) Error() string

type InvalidUnicodeCharError

type InvalidUnicodeCharError struct {
	// contains filtered or unexported fields
}

InvalidUnicodeCharError

func (InvalidUnicodeCharError) Error

func (e InvalidUnicodeCharError) Error() string

type Iterator

type Iterator struct {
	// contains filtered or unexported fields
}

func NewIterator

func NewIterator() *Iterator

func (*Iterator) AppendRaw

func (it *Iterator) AppendRaw(in []byte) ([]byte, error)

copy version

func (*Iterator) Buffer

func (it *Iterator) Buffer() []byte

func (*Iterator) NextValueType

func (it *Iterator) NextValueType() (ValueType, error)

Read until the first valid token is found, only the whitespaces are consumed

func (*Iterator) Read

func (it *Iterator) Read() (interface{}, error)

func (*Iterator) ReadArrayBegin

func (it *Iterator) ReadArrayBegin() (ret bool, err error)

* var ( * more bool * err error * ) * for more, err = it.ReadArray(); * more; * more, err = it.ReadArrayMore() { * } * if err != nil { * // error handling * }

func (*Iterator) ReadArrayCB

func (it *Iterator) ReadArrayCB(cb func(*Iterator) error) error

func (*Iterator) ReadArrayMore

func (it *Iterator) ReadArrayMore() (ret bool, err error)

func (*Iterator) ReadBool

func (it *Iterator) ReadBool() (bool, error)

func (*Iterator) ReadFloat32

func (it *Iterator) ReadFloat32() (float32, error)

func (*Iterator) ReadFloat64

func (it *Iterator) ReadFloat64() (float64, error)

func (*Iterator) ReadInt

func (it *Iterator) ReadInt() (int, error)

func (*Iterator) ReadInt16

func (it *Iterator) ReadInt16() (int16, error)

func (*Iterator) ReadInt32

func (it *Iterator) ReadInt32() (int32, error)

func (*Iterator) ReadInt64

func (it *Iterator) ReadInt64() (int64, error)

func (*Iterator) ReadInt8

func (it *Iterator) ReadInt8() (int8, error)

func (*Iterator) ReadNull

func (it *Iterator) ReadNull() error

func (*Iterator) ReadNumber

func (it *Iterator) ReadNumber() (n Number, err error)

func (*Iterator) ReadObjectBegin

func (it *Iterator) ReadObjectBegin() (_ bool, _ string, err error)

func (*Iterator) ReadObjectCB

func (it *Iterator) ReadObjectCB(cb func(it *Iterator, field string) error) error

func (*Iterator) ReadObjectMore

func (it *Iterator) ReadObjectMore() (_ bool, _ string, err error)

func (*Iterator) ReadRaw

func (it *Iterator) ReadRaw() ([]byte, error)

copy version

func (*Iterator) ReadString

func (it *Iterator) ReadString() (ret string, err error)

func (*Iterator) ReadStringAndAppend

func (it *Iterator) ReadStringAndAppend(buf []byte) (_ []byte, err error)

func (*Iterator) ReadStringAsSlice

func (it *Iterator) ReadStringAsSlice() (_ []byte, err error)

The returned slice can only be used temporarily, a copy must be made if the result needs to be saved

func (*Iterator) ReadUint

func (it *Iterator) ReadUint() (uint, error)

func (*Iterator) ReadUint16

func (it *Iterator) ReadUint16() (uint16, error)

func (*Iterator) ReadUint32

func (it *Iterator) ReadUint32() (uint32, error)

func (*Iterator) ReadUint64

func (it *Iterator) ReadUint64() (uint64, error)

func (*Iterator) ReadUint8

func (it *Iterator) ReadUint8() (uint8, error)

func (*Iterator) ReadVal

func (it *Iterator) ReadVal(obj interface{}) error

func (*Iterator) Reset

func (it *Iterator) Reset(r io.Reader)

* In reset methods, explicit assignment is faster than then following * *it = Iterator{ ... } * When the above code is used, runtime.duffcopy and runtime.duffzero will be used * which will slow down our code (correct me if I am wrong)

func (*Iterator) ResetBytes

func (it *Iterator) ResetBytes(data []byte)

func (*Iterator) Skip

func (it *Iterator) Skip() error

func (*Iterator) SkipArray

func (it *Iterator) SkipArray() error

func (*Iterator) SkipNumber

func (it *Iterator) SkipNumber() error

func (*Iterator) SkipObject

func (it *Iterator) SkipObject() error

func (*Iterator) SkipRaw

func (it *Iterator) SkipRaw() ([]byte, error)

No copy version

func (*Iterator) SkipString

func (it *Iterator) SkipString() error

func (*Iterator) Unmarshal

func (it *Iterator) Unmarshal(data []byte, obj interface{}) error

func (*Iterator) UnmarshalFromReader added in v0.0.3

func (it *Iterator) UnmarshalFromReader(r io.Reader, obj interface{}) error

func (*Iterator) Valid

func (it *Iterator) Valid(data []byte) bool

func (*Iterator) WrapError

func (it *Iterator) WrapError(err error) *DecodeError

type IteratorPool

type IteratorPool struct {
	// contains filtered or unexported fields
}

func NewIteratorPool

func NewIteratorPool() *IteratorPool

func (*IteratorPool) BorrowIterator

func (p *IteratorPool) BorrowIterator() *Iterator

func (*IteratorPool) ReturnIterator

func (p *IteratorPool) ReturnIterator(it *Iterator)

type Number

type Number = json.Number

type Streamer

type Streamer struct {
	Error error

	Context interface{} // custom stream context
	// contains filtered or unexported fields
}

func NewStreamer

func NewStreamer() *Streamer

func (*Streamer) ArrayEnd

func (s *Streamer) ArrayEnd() *Streamer

func (*Streamer) ArrayStart

func (s *Streamer) ArrayStart() *Streamer

func (*Streamer) Bool

func (s *Streamer) Bool(b bool) *Streamer

func (*Streamer) False

func (s *Streamer) False() *Streamer

func (*Streamer) Field

func (s *Streamer) Field(field string) *Streamer

func (*Streamer) Float32

func (s *Streamer) Float32(f float32) *Streamer

func (*Streamer) Float64

func (s *Streamer) Float64(f float64) *Streamer

func (*Streamer) Flush

func (s *Streamer) Flush() error

func (*Streamer) Int

func (s *Streamer) Int(v int) *Streamer

func (*Streamer) Int16

func (s *Streamer) Int16(v int16) *Streamer

func (*Streamer) Int32

func (s *Streamer) Int32(v int32) *Streamer

func (*Streamer) Int64

func (s *Streamer) Int64(v int64) *Streamer

func (*Streamer) Int8

func (s *Streamer) Int8(v int8) *Streamer

func (*Streamer) Null

func (s *Streamer) Null() *Streamer

func (*Streamer) ObjectEnd

func (s *Streamer) ObjectEnd() *Streamer

func (*Streamer) ObjectStart

func (s *Streamer) ObjectStart() *Streamer

func (*Streamer) Raw

func (s *Streamer) Raw(raw []byte) *Streamer

func (*Streamer) RawField

func (s *Streamer) RawField(b []byte) *Streamer

func (*Streamer) RawString

func (s *Streamer) RawString(raw string) *Streamer

func (*Streamer) Reset

func (s *Streamer) Reset(w io.Writer)

func (*Streamer) String

func (s *Streamer) String(str string) *Streamer

func (*Streamer) True

func (s *Streamer) True() *Streamer

func (*Streamer) Uint

func (s *Streamer) Uint(v uint) *Streamer

func (*Streamer) Uint16

func (s *Streamer) Uint16(v uint16) *Streamer

func (*Streamer) Uint32

func (s *Streamer) Uint32(v uint32) *Streamer

func (*Streamer) Uint64

func (s *Streamer) Uint64(v uint64) *Streamer

func (*Streamer) Uint8

func (s *Streamer) Uint8(v uint8) *Streamer

func (*Streamer) Value

func (s *Streamer) Value(obj interface{}) *Streamer

type StreamerPool

type StreamerPool struct {
	// contains filtered or unexported fields
}

func NewStreamerPool

func NewStreamerPool() *StreamerPool

func (*StreamerPool) BorrowStreamer

func (p *StreamerPool) BorrowStreamer() *Streamer

func (*StreamerPool) ReturnStreamer

func (p *StreamerPool) ReturnStreamer(s *Streamer)

type TypeNotSupportedError

type TypeNotSupportedError string

TypeNotSupported

func (TypeNotSupportedError) Error

func (e TypeNotSupportedError) Error() string

type UnexpectedByteError

type UnexpectedByteError struct {
	// contains filtered or unexported fields
}

UnexpectedByteError

func (UnexpectedByteError) Error

func (e UnexpectedByteError) Error() string

type UnknownFieldError

type UnknownFieldError string

UnknownField

func (UnknownFieldError) Error

func (e UnknownFieldError) Error() string

type ValDecoder

type ValDecoder interface {
	Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error
}

type ValEncoder

type ValEncoder interface {
	IsEmpty(ptr unsafe.Pointer) bool

	Encode(ptr unsafe.Pointer, s *Streamer, opts *EncOpts)
}

type ValueType

type ValueType int
const (
	WhiteSpaceValue ValueType = iota
	InvalidValue
	StringValue
	NumberValue
	ObjectValue
	ArrayValue
	BoolValue
	NullValue
	LastValue
)

Source Files

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL