1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-23 11:37:32 +02:00

array encoder

This commit is contained in:
Tao Wen 2017-01-09 19:48:57 +08:00
parent 552afb3625
commit 90fc0b822f
5 changed files with 74 additions and 12 deletions

View File

@ -359,7 +359,7 @@ func decoderOfType(typ reflect.Type) (Decoder, error) {
case reflect.Interface:
return &interfaceDecoder{}, nil
case reflect.Struct:
return decoderOfStruct(typ)
return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(typ))
case reflect.Slice:
return prefix("[slice]").addToDecoder(decoderOfSlice(typ))
case reflect.Map:
@ -374,6 +374,7 @@ func decoderOfType(typ reflect.Type) (Decoder, error) {
func encoderOfType(typ reflect.Type) (Encoder, error) {
typeName := typ.String()
switch typ.Kind() {
case reflect.String:
return &stringCodec{}, nil
@ -404,7 +405,9 @@ func encoderOfType(typ reflect.Type) (Encoder, error) {
case reflect.Bool:
return &boolCodec{}, nil
case reflect.Struct:
return encoderOfStruct(typ)
return prefix(fmt.Sprintf("[%s]", typeName)).addToEncoder(encoderOfStruct(typ))
case reflect.Slice:
return prefix("[slice]").addToEncoder(encoderOfSlice(typ))
default:
return nil, fmt.Errorf("unsupported type: %v", typ)
}
@ -418,14 +421,6 @@ func decoderOfOptional(typ reflect.Type) (Decoder, error) {
return &optionalDecoder{typ, decoder}, nil
}
func decoderOfSlice(typ reflect.Type) (Decoder, error) {
decoder, err := decoderOfType(typ.Elem())
if err != nil {
return nil, err
}
return &sliceDecoder{typ, typ.Elem(), decoder}, nil
}
func decoderOfMap(typ reflect.Type) (Decoder, error) {
decoder, err := decoderOfType(typ.Elem())
if err != nil {

View File

@ -7,6 +7,48 @@ import (
"fmt"
)
func decoderOfSlice(typ reflect.Type) (Decoder, error) {
decoder, err := decoderOfType(typ.Elem())
if err != nil {
return nil, err
}
return &sliceDecoder{typ, typ.Elem(), decoder}, nil
}
func encoderOfSlice(typ reflect.Type) (Encoder, error) {
encoder, err := encoderOfType(typ.Elem())
if err != nil {
return nil, err
}
return &sliceEncoder{typ, typ.Elem(), encoder}, nil
}
type sliceEncoder struct {
sliceType reflect.Type
elemType reflect.Type
elemEncoder Encoder
}
func (encoder *sliceEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
slice := (*sliceHeader)(ptr)
if slice.Len == 0 {
stream.WriteEmptyArray()
return
}
stream.WriteArrayStart()
elemPtr := uintptr(slice.Data)
encoder.elemEncoder.encode(unsafe.Pointer(elemPtr), stream)
for i := 1; i < slice.Len; i++ {
stream.WriteMore()
elemPtr += encoder.elemType.Size()
encoder.elemEncoder.encode(unsafe.Pointer(elemPtr), stream)
}
stream.WriteArrayEnd()
if stream.Error != nil && stream.Error != io.EOF {
stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error())
}
}
type sliceDecoder struct {
sliceType reflect.Type
elemType reflect.Type

View File

@ -415,6 +415,5 @@ type emptyStructEncoder struct {
}
func (encoder *emptyStructEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteObjectStart()
stream.WriteObjectEnd()
stream.WriteEmptyObject()
}

View File

@ -134,6 +134,22 @@ func Test_write_array(t *testing.T) {
should.Equal("[\n 1,\n 2\n]", buf.String())
}
func Test_write_val_array(t *testing.T) {
should := require.New(t)
val := []int{1,2,3}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal("[1,2,3]", str)
}
func Test_write_val_empty_array(t *testing.T) {
should := require.New(t)
val := []int{}
str, err := MarshalToString(val)
should.Nil(err)
should.Equal("[]", str)
}
func Benchmark_jsoniter_array(b *testing.B) {
b.ReportAllocs()
input := []byte(`[1,2,3,4,5,6,7,8,9]`)

View File

@ -171,6 +171,11 @@ func (stream *Stream) WriteObjectEnd() {
stream.writeByte('}')
}
func (stream *Stream) WriteEmptyObject() {
stream.writeByte('{')
stream.writeByte('}')
}
func (stream *Stream) WriteMore() {
stream.writeByte(',')
stream.writeIndention(0)
@ -182,6 +187,11 @@ func (stream *Stream) WriteArrayStart() {
stream.writeIndention(0)
}
func (stream *Stream) WriteEmptyArray() {
stream.writeByte('[')
stream.writeByte(']')
}
func (stream *Stream) WriteArrayEnd() {
stream.writeIndention(stream.IndentionStep)
stream.indention -= stream.IndentionStep