github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/jsoni/extension_tests/decoder_test.go (about) 1 package test 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "strconv" 8 "testing" 9 "time" 10 "unsafe" 11 12 "github.com/bingoohuang/gg/pkg/jsoni" 13 "github.com/modern-go/reflect2" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func Test_customize_type_decoder(t *testing.T) { 18 t.Skip() 19 jsoni.RegisterTypeDecoderFunc("time.Time", func(ctx context.Context, ptr unsafe.Pointer, iter *jsoni.Iterator) { 20 t, err := time.ParseInLocation("2006-01-02 15:04:05", iter.ReadString(), time.UTC) 21 if err != nil { 22 iter.Error = err 23 return 24 } 25 *((*time.Time)(ptr)) = t 26 }) 27 // defer jsoni.ConfigDefault.(*frozenConfig).cleanDecoders() 28 val := time.Time{} 29 err := jsoni.Unmarshal([]byte(`"2016-12-05 08:43:28"`), &val) 30 if err != nil { 31 t.Fatal(err) 32 } 33 year, month, day := val.Date() 34 if year != 2016 || month != 12 || day != 5 { 35 t.Fatal(val) 36 } 37 } 38 39 func Test_customize_byte_array_encoder(t *testing.T) { 40 t.Skip() 41 // jsoni.ConfigDefault.(*frozenConfig).cleanEncoders() 42 should := require.New(t) 43 jsoni.RegisterTypeEncoderFunc("[]uint8", func(_ context.Context, ptr unsafe.Pointer, stream *jsoni.Stream) { 44 t := *((*[]byte)(ptr)) 45 stream.WriteString(string(t)) 46 }, nil) 47 // defer jsoni.ConfigDefault.(*frozenConfig).cleanEncoders() 48 val := []byte("abc") 49 str, err := jsoni.MarshalToString(val) 50 should.Nil(err) 51 should.Equal(`"abc"`, str) 52 } 53 54 type CustomEncoderAttachmentTestStruct struct { 55 Value int32 `json:"value"` 56 } 57 58 type CustomEncoderAttachmentTestStructEncoder struct{} 59 60 func (c *CustomEncoderAttachmentTestStructEncoder) Encode(_ context.Context, _ unsafe.Pointer, stream *jsoni.Stream) { 61 attachVal, ok := stream.Attachment.(int) 62 stream.WriteRaw(`"`) 63 stream.WriteRaw(fmt.Sprintf("%t %d", ok, attachVal)) 64 stream.WriteRaw(`"`) 65 } 66 67 func (c *CustomEncoderAttachmentTestStructEncoder) IsEmpty(context.Context, unsafe.Pointer, bool) bool { 68 return false 69 } 70 71 func Test_custom_encoder_attachment(t *testing.T) { 72 expectedValue := 17 73 should := require.New(t) 74 buf := &bytes.Buffer{} 75 config := jsoni.Config{SortMapKeys: true}.Froze() 76 config.RegisterTypeEncoder(reflect2.TypeOf(CustomEncoderAttachmentTestStruct{}).String(), 77 &CustomEncoderAttachmentTestStructEncoder{}) 78 79 stream := jsoni.NewStream(config, buf, 4096) 80 stream.Attachment = expectedValue 81 val := map[string]CustomEncoderAttachmentTestStruct{"a": {}} 82 stream.WriteVal(context.Background(), val) 83 stream.Flush() 84 should.Nil(stream.Error) 85 should.Equal("{\"a\":\"true 17\"}", buf.String()) 86 } 87 88 func Test_customize_field_decoder(t *testing.T) { 89 type Tom struct { 90 field1 string 91 } 92 jsoni.RegisterFieldDecoderFunc("jsoni.Tom", "field1", func(ctx context.Context, ptr unsafe.Pointer, iter *jsoni.Iterator) { 93 *((*string)(ptr)) = strconv.Itoa(iter.ReadInt()) 94 }) 95 // defer jsoni.ConfigDefault.(*frozenConfig).cleanDecoders() 96 tom := Tom{} 97 err := jsoni.Unmarshal([]byte(`{"field1": 100}`), &tom) 98 if err != nil { 99 t.Fatal(err) 100 } 101 } 102 103 func Test_recursive_empty_interface_customization(t *testing.T) { 104 t.Skip() 105 var obj interface{} 106 jsoni.RegisterTypeDecoderFunc("interface {}", func(ctx context.Context, ptr unsafe.Pointer, iter *jsoni.Iterator) { 107 switch iter.WhatIsNext() { 108 case jsoni.NumberValue: 109 *(*interface{})(ptr) = iter.ReadInt64() 110 default: 111 *(*interface{})(ptr) = iter.Read(ctx) 112 } 113 }) 114 should := require.New(t) 115 jsoni.Unmarshal([]byte("[100]"), &obj) 116 should.Equal([]interface{}{int64(100)}, obj) 117 } 118 119 type MyInterface interface { 120 Hello() string 121 } 122 123 type MyString string 124 125 func (ms MyString) Hello() string { 126 return string(ms) 127 } 128 129 func Test_read_custom_interface(t *testing.T) { 130 t.Skip() 131 should := require.New(t) 132 var val MyInterface 133 jsoni.RegisterTypeDecoderFunc("jsoni.MyInterface", func(ctx context.Context, ptr unsafe.Pointer, iter *jsoni.Iterator) { 134 *((*MyInterface)(ptr)) = MyString(iter.ReadString()) 135 }) 136 err := jsoni.UnmarshalFromString(`"hello"`, &val) 137 should.Nil(err) 138 should.Equal("hello", val.Hello()) 139 } 140 141 const flow1 = ` 142 {"A":"hello"} 143 {"A":"hello"} 144 {"A":"hello"} 145 {"A":"hello"} 146 {"A":"hello"}` 147 148 const flow2 = ` 149 {"A":"hello"} 150 {"A":"hello"} 151 {"A":"hello"} 152 {"A":"hello"} 153 {"A":"hello"} 154 ` 155 156 type ( 157 Type1 struct { 158 A string 159 } 160 161 Type2 struct { 162 A string 163 } 164 ) 165 166 func (t *Type2) UnmarshalJSON(data []byte) error { 167 return nil 168 } 169 170 func (t *Type2) MarshalJSON() ([]byte, error) { 171 return nil, nil 172 } 173 174 func TestType1NoFinalLF(t *testing.T) { 175 reader := bytes.NewReader([]byte(flow1)) 176 dec := jsoni.NewDecoder(reader) 177 ctx := context.Background() 178 i := 0 179 for dec.More() { 180 data := &Type1{} 181 if err := dec.Decode(ctx, data); err != nil { 182 t.Errorf("at %v got %v", i, err) 183 } 184 i++ 185 } 186 } 187 188 func TestType1FinalLF(t *testing.T) { 189 reader := bytes.NewReader([]byte(flow2)) 190 dec := jsoni.NewDecoder(reader) 191 192 i := 0 193 ctx := context.Background() 194 for dec.More() { 195 data := &Type1{} 196 if err := dec.Decode(ctx, data); err != nil { 197 t.Errorf("at %v got %v", i, err) 198 } 199 i++ 200 } 201 } 202 203 func TestType2NoFinalLF(t *testing.T) { 204 reader := bytes.NewReader([]byte(flow1)) 205 dec := jsoni.NewDecoder(reader) 206 ctx := context.Background() 207 i := 0 208 for dec.More() { 209 data := &Type2{} 210 if err := dec.Decode(ctx, data); err != nil { 211 t.Errorf("at %v got %v", i, err) 212 } 213 i++ 214 } 215 } 216 217 func TestType2FinalLF(t *testing.T) { 218 reader := bytes.NewReader([]byte(flow2)) 219 dec := jsoni.NewDecoder(reader) 220 ctx := context.Background() 221 i := 0 222 for dec.More() { 223 data := &Type2{} 224 if err := dec.Decode(ctx, data); err != nil { 225 t.Errorf("at %v got %v", i, err) 226 } 227 i++ 228 } 229 }