mirror of
https://github.com/json-iterator/go.git
synced 2025-04-26 11:42:56 +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:
|
case reflect.Interface:
|
||||||
return &interfaceDecoder{}, nil
|
return &interfaceDecoder{}, nil
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return decoderOfStruct(typ)
|
return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(typ))
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return prefix("[slice]").addToDecoder(decoderOfSlice(typ))
|
return prefix("[slice]").addToDecoder(decoderOfSlice(typ))
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
@ -374,6 +374,7 @@ func decoderOfType(typ reflect.Type) (Decoder, error) {
|
|||||||
|
|
||||||
|
|
||||||
func encoderOfType(typ reflect.Type) (Encoder, error) {
|
func encoderOfType(typ reflect.Type) (Encoder, error) {
|
||||||
|
typeName := typ.String()
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return &stringCodec{}, nil
|
return &stringCodec{}, nil
|
||||||
@ -404,7 +405,9 @@ func encoderOfType(typ reflect.Type) (Encoder, error) {
|
|||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
return &boolCodec{}, nil
|
return &boolCodec{}, nil
|
||||||
case reflect.Struct:
|
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:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported type: %v", typ)
|
return nil, fmt.Errorf("unsupported type: %v", typ)
|
||||||
}
|
}
|
||||||
@ -418,14 +421,6 @@ func decoderOfOptional(typ reflect.Type) (Decoder, error) {
|
|||||||
return &optionalDecoder{typ, decoder}, nil
|
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) {
|
func decoderOfMap(typ reflect.Type) (Decoder, error) {
|
||||||
decoder, err := decoderOfType(typ.Elem())
|
decoder, err := decoderOfType(typ.Elem())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,6 +7,48 @@ import (
|
|||||||
"fmt"
|
"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 {
|
type sliceDecoder struct {
|
||||||
sliceType reflect.Type
|
sliceType reflect.Type
|
||||||
elemType reflect.Type
|
elemType reflect.Type
|
||||||
|
@ -415,6 +415,5 @@ type emptyStructEncoder struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (encoder *emptyStructEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
|
func (encoder *emptyStructEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
stream.WriteObjectStart()
|
stream.WriteEmptyObject()
|
||||||
stream.WriteObjectEnd()
|
|
||||||
}
|
}
|
@ -134,6 +134,22 @@ func Test_write_array(t *testing.T) {
|
|||||||
should.Equal("[\n 1,\n 2\n]", buf.String())
|
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) {
|
func Benchmark_jsoniter_array(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
input := []byte(`[1,2,3,4,5,6,7,8,9]`)
|
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('}')
|
stream.writeByte('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (stream *Stream) WriteEmptyObject() {
|
||||||
|
stream.writeByte('{')
|
||||||
|
stream.writeByte('}')
|
||||||
|
}
|
||||||
|
|
||||||
func (stream *Stream) WriteMore() {
|
func (stream *Stream) WriteMore() {
|
||||||
stream.writeByte(',')
|
stream.writeByte(',')
|
||||||
stream.writeIndention(0)
|
stream.writeIndention(0)
|
||||||
@ -182,6 +187,11 @@ func (stream *Stream) WriteArrayStart() {
|
|||||||
stream.writeIndention(0)
|
stream.writeIndention(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (stream *Stream) WriteEmptyArray() {
|
||||||
|
stream.writeByte('[')
|
||||||
|
stream.writeByte(']')
|
||||||
|
}
|
||||||
|
|
||||||
func (stream *Stream) WriteArrayEnd() {
|
func (stream *Stream) WriteArrayEnd() {
|
||||||
stream.writeIndention(stream.IndentionStep)
|
stream.writeIndention(stream.IndentionStep)
|
||||||
stream.indention -= stream.IndentionStep
|
stream.indention -= stream.IndentionStep
|
||||||
|
Loading…
x
Reference in New Issue
Block a user