// 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 ( "bytes" "encoding/json" "errors" "io" "reflect" "unsafe" ) // Unmarshal adapts to json/encoding Unmarshal API // // Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. // Refer to https://godoc.org/encoding/json#Unmarshal for more information func Unmarshal(data []byte, v interface{}) error { data = data[:lastNotSpacePos(data)] iter := ParseBytes(data) typ := reflect.TypeOf(v) if typ.Kind() != reflect.Ptr { // return non-pointer error return errors.New("the second param must be ptr type") } iter.ReadVal(v) if iter.head == iter.tail { iter.loadMore() } if iter.Error == io.EOF { return nil } if iter.Error == nil { iter.reportError("Unmarshal", "there are bytes left after unmarshal") } return iter.Error } // UnmarshalAny adapts to func UnmarshalAny(data []byte) (Any, error) { data = data[:lastNotSpacePos(data)] iter := ParseBytes(data) any := iter.ReadAny() if iter.head == iter.tail { iter.loadMore() } if iter.Error == io.EOF { return any, nil } if iter.Error == nil { iter.reportError("UnmarshalAny", "there are bytes left after unmarshal") } return any, iter.Error } func lastNotSpacePos(data []byte) int { for i := len(data) - 1; i >= 0; i-- { if data[i] != ' ' && data[i] != '\t' && data[i] != '\r' && data[i] != '\n' { return i + 1 } } return 0 } func UnmarshalFromString(str string, v interface{}) error { data := []byte(str) data = data[:lastNotSpacePos(data)] iter := ParseBytes(data) iter.ReadVal(v) if iter.head == iter.tail { iter.loadMore() } if iter.Error == io.EOF { return nil } if iter.Error == nil { iter.reportError("UnmarshalFromString", "there are bytes left after unmarshal") } return iter.Error } func UnmarshalAnyFromString(str string) (Any, error) { data := []byte(str) data = data[:lastNotSpacePos(data)] iter := ParseBytes(data) any := iter.ReadAny() if iter.head == iter.tail { iter.loadMore() } if iter.Error == io.EOF { return any, nil } if iter.Error == nil { iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal") } return nil, iter.Error } // Marshal adapts to json/encoding Marshal API // // Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API // Refer to https://godoc.org/encoding/json#Marshal for more information func Marshal(v interface{}) ([]byte, error) { stream := NewStream(nil, 256) stream.WriteVal(v) if stream.Error != nil { return nil, stream.Error } return stream.Buffer(), nil } func MarshalToString(v interface{}) (string, error) { buf, err := Marshal(v) if err != nil { return "", err } return string(buf), nil } // NewDecoder adapts to json/stream NewDecoder API. // // NewDecoder returns a new decoder that reads from r. // // Instead of a json/encoding Decoder, an AdaptedDecoder is returned // Refer to https://godoc.org/encoding/json#NewDecoder for more information func NewDecoder(reader io.Reader) *AdaptedDecoder { iter := Parse(reader, 512) return &AdaptedDecoder{iter} } // AdaptedDecoder reads and decodes JSON values from an input stream. // AdaptedDecoder provides identical APIs with json/stream Decoder (Token() and UseNumber() are in progress) type AdaptedDecoder struct { iter *Iterator } func (adapter *AdaptedDecoder) Decode(obj interface{}) error { adapter.iter.ReadVal(obj) err := adapter.iter.Error if err == io.EOF { return nil } return adapter.iter.Error } func (adapter *AdaptedDecoder) More() bool { return adapter.iter.head != adapter.iter.tail } func (adapter *AdaptedDecoder) Buffered() io.Reader { remaining := adapter.iter.buf[adapter.iter.head:adapter.iter.tail] return bytes.NewReader(remaining) } func (decoder *AdaptedDecoder) UseNumber() { RegisterTypeDecoder("interface {}", func(ptr unsafe.Pointer, iter *Iterator) { if iter.WhatIsNext() == Number { *((*interface{})(ptr)) = json.Number(iter.readNumberAsString()) } else { *((*interface{})(ptr)) = iter.Read() } }) } func NewEncoder(writer io.Writer) *AdaptedEncoder { stream := NewStream(writer, 512) return &AdaptedEncoder{stream} } type AdaptedEncoder struct { stream *Stream } func (adapter *AdaptedEncoder) Encode(val interface{}) error { adapter.stream.WriteVal(val) adapter.stream.Flush() return adapter.stream.Error } func (adapter *AdaptedEncoder) SetIndent(prefix, indent string) { adapter.stream.IndentionStep = len(indent) }