...

Source file src/github.com/json-iterator/go/extension_tests/extension_test.go

Documentation: github.com/json-iterator/go/extension_tests

     1  package test
     2  
     3  import (
     4  	"github.com/json-iterator/go"
     5  	"github.com/modern-go/reflect2"
     6  	"github.com/stretchr/testify/require"
     7  	"reflect"
     8  	"strconv"
     9  	"testing"
    10  	"unsafe"
    11  )
    12  
    13  type TestObject1 struct {
    14  	Field1 string
    15  }
    16  
    17  type testExtension struct {
    18  	jsoniter.DummyExtension
    19  }
    20  
    21  func (extension *testExtension) UpdateStructDescriptor(structDescriptor *jsoniter.StructDescriptor) {
    22  	if structDescriptor.Type.String() != "test.TestObject1" {
    23  		return
    24  	}
    25  	binding := structDescriptor.GetField("Field1")
    26  	binding.Encoder = &funcEncoder{fun: func(ptr unsafe.Pointer, stream *jsoniter.Stream) {
    27  		str := *((*string)(ptr))
    28  		val, _ := strconv.Atoi(str)
    29  		stream.WriteInt(val)
    30  	}}
    31  	binding.Decoder = &funcDecoder{func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
    32  		*((*string)(ptr)) = strconv.Itoa(iter.ReadInt())
    33  	}}
    34  	binding.ToNames = []string{"field-1"}
    35  	binding.FromNames = []string{"field-1"}
    36  }
    37  
    38  func Test_customize_field_by_extension(t *testing.T) {
    39  	should := require.New(t)
    40  	cfg := jsoniter.Config{}.Froze()
    41  	cfg.RegisterExtension(&testExtension{})
    42  	obj := TestObject1{}
    43  	err := cfg.UnmarshalFromString(`{"field-1": 100}`, &obj)
    44  	should.Nil(err)
    45  	should.Equal("100", obj.Field1)
    46  	str, err := cfg.MarshalToString(obj)
    47  	should.Nil(err)
    48  	should.Equal(`{"field-1":100}`, str)
    49  }
    50  
    51  func Test_customize_map_key_encoder(t *testing.T) {
    52  	should := require.New(t)
    53  	cfg := jsoniter.Config{}.Froze()
    54  	cfg.RegisterExtension(&testMapKeyExtension{})
    55  	m := map[int]int{1: 2}
    56  	output, err := cfg.MarshalToString(m)
    57  	should.NoError(err)
    58  	should.Equal(`{"2":2}`, output)
    59  	m = map[int]int{}
    60  	should.NoError(cfg.UnmarshalFromString(output, &m))
    61  	should.Equal(map[int]int{1: 2}, m)
    62  }
    63  
    64  type testMapKeyExtension struct {
    65  	jsoniter.DummyExtension
    66  }
    67  
    68  func (extension *testMapKeyExtension) CreateMapKeyEncoder(typ reflect2.Type) jsoniter.ValEncoder {
    69  	if typ.Kind() == reflect.Int {
    70  		return &funcEncoder{
    71  			fun: func(ptr unsafe.Pointer, stream *jsoniter.Stream) {
    72  				stream.WriteRaw(`"`)
    73  				stream.WriteInt(*(*int)(ptr) + 1)
    74  				stream.WriteRaw(`"`)
    75  			},
    76  		}
    77  	}
    78  	return nil
    79  }
    80  
    81  func (extension *testMapKeyExtension) CreateMapKeyDecoder(typ reflect2.Type) jsoniter.ValDecoder {
    82  	if typ.Kind() == reflect.Int {
    83  		return &funcDecoder{
    84  			fun: func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
    85  				i, err := strconv.Atoi(iter.ReadString())
    86  				if err != nil {
    87  					iter.ReportError("read map key", err.Error())
    88  					return
    89  				}
    90  				i--
    91  				*(*int)(ptr) = i
    92  			},
    93  		}
    94  	}
    95  	return nil
    96  }
    97  
    98  type funcDecoder struct {
    99  	fun jsoniter.DecoderFunc
   100  }
   101  
   102  func (decoder *funcDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
   103  	decoder.fun(ptr, iter)
   104  }
   105  
   106  type funcEncoder struct {
   107  	fun         jsoniter.EncoderFunc
   108  	isEmptyFunc func(ptr unsafe.Pointer) bool
   109  }
   110  
   111  func (encoder *funcEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
   112  	encoder.fun(ptr, stream)
   113  }
   114  
   115  func (encoder *funcEncoder) IsEmpty(ptr unsafe.Pointer) bool {
   116  	if encoder.isEmptyFunc == nil {
   117  		return false
   118  	}
   119  	return encoder.isEmptyFunc(ptr)
   120  }
   121  

View as plain text