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:
parent
552afb3625
commit
90fc0b822f
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -415,6 +415,5 @@ type emptyStructEncoder struct {
|
||||
}
|
||||
|
||||
func (encoder *emptyStructEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
|
||||
stream.WriteObjectStart()
|
||||
stream.WriteObjectEnd()
|
||||
stream.WriteEmptyObject()
|
||||
}
|
@ -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]`)
|
||||
|
10
stream.go
10
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user