diff --git a/feature_reflect.go b/feature_reflect.go index 56d7c90..e95e542 100644 --- a/feature_reflect.go +++ b/feature_reflect.go @@ -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 { diff --git a/feature_reflect_array.go b/feature_reflect_array.go index 275083b..9227203 100644 --- a/feature_reflect_array.go +++ b/feature_reflect_array.go @@ -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 diff --git a/feature_reflect_object.go b/feature_reflect_object.go index c66d853..74ae1ac 100644 --- a/feature_reflect_object.go +++ b/feature_reflect_object.go @@ -415,6 +415,5 @@ type emptyStructEncoder struct { } func (encoder *emptyStructEncoder) encode(ptr unsafe.Pointer, stream *Stream) { - stream.WriteObjectStart() - stream.WriteObjectEnd() + stream.WriteEmptyObject() } \ No newline at end of file diff --git a/jsoniter_array_test.go b/jsoniter_array_test.go index 285994f..11b4078 100644 --- a/jsoniter_array_test.go +++ b/jsoniter_array_test.go @@ -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]`) diff --git a/stream.go b/stream.go index d19d6f9..77cef31 100644 --- a/stream.go +++ b/stream.go @@ -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