github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/decoder_config_test.go (about)

     1  package jzon
     2  
     3  import (
     4  	"reflect"
     5  	"runtime/debug"
     6  	"testing"
     7  	"unsafe"
     8  
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  type testIntDecoder struct{}
    13  
    14  func (*testIntDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error {
    15  	vt, err := it.NextValueType()
    16  	if err != nil {
    17  		return err
    18  	}
    19  	switch vt {
    20  	case NullValue:
    21  		if err := it.ReadNull(); err != nil {
    22  			return err
    23  		}
    24  		*(*int)(ptr) = 1
    25  		return nil
    26  	default:
    27  		i, err := it.ReadInt()
    28  		if err != nil {
    29  			return err
    30  		}
    31  		*(*int)(ptr) = i * 2
    32  		return nil
    33  	}
    34  }
    35  
    36  type testPtrDecoder struct{}
    37  
    38  func (*testPtrDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error {
    39  	vt, err := it.NextValueType()
    40  	if err != nil {
    41  		return err
    42  	}
    43  	switch vt {
    44  	case NullValue:
    45  		if err := it.ReadNull(); err != nil {
    46  			return err
    47  		}
    48  		v := -1
    49  		*(**int)(ptr) = &v
    50  		return nil
    51  	default:
    52  		i, err := it.ReadInt()
    53  		if err != nil {
    54  			return err
    55  		}
    56  		i = i * 2
    57  		*(**int)(ptr) = &i
    58  		return nil
    59  	}
    60  }
    61  
    62  func TestDecoderConfig_CustomConfig(t *testing.T) {
    63  	t.Run("int", func(t *testing.T) {
    64  		decCfg := NewDecoderConfig(&DecoderOption{
    65  			ValDecoders: map[reflect.Type]ValDecoder{
    66  				reflect.TypeOf(int(0)): (*testIntDecoder)(nil),
    67  			},
    68  			CaseSensitive: true,
    69  		})
    70  		t.Run("value", func(t *testing.T) {
    71  			t.Run("null", func(t *testing.T) {
    72  				var i int
    73  				err := decCfg.UnmarshalFromString("null", &i)
    74  				require.NoError(t, err)
    75  				require.Equal(t, 1, i)
    76  			})
    77  			t.Run("not null", func(t *testing.T) {
    78  				var i int
    79  				err := decCfg.UnmarshalFromString("1", &i)
    80  				require.NoError(t, err)
    81  				require.Equal(t, 2, i)
    82  			})
    83  		})
    84  		t.Run("pointer", func(t *testing.T) {
    85  			t.Run("null on not null", func(t *testing.T) {
    86  				v := 1
    87  				i := &v
    88  				err := decCfg.UnmarshalFromString("null", &i)
    89  				require.NoError(t, err)
    90  				require.Nil(t, i)
    91  			})
    92  			t.Run("not null", func(t *testing.T) {
    93  				v := -1
    94  				i := &v
    95  				err := decCfg.UnmarshalFromString("2", &i)
    96  				require.NoError(t, err)
    97  				require.NotNil(t, i)
    98  				require.Equal(t, 4, v)
    99  			})
   100  		})
   101  		t.Run("field", func(t *testing.T) {
   102  			t.Run("value", func(t *testing.T) {
   103  				st := struct {
   104  					A int `json:"a"`
   105  				}{}
   106  				t.Run("not present", func(t *testing.T) {
   107  					v := 1
   108  					st.A = v
   109  					err := decCfg.UnmarshalFromString(`{}`, &st)
   110  					require.NoError(t, err)
   111  					require.Equal(t, v, st.A)
   112  				})
   113  				t.Run("null", func(t *testing.T) {
   114  					st.A = -1
   115  					err := decCfg.UnmarshalFromString(`{"a":null}`, &st)
   116  					require.NoError(t, err)
   117  					require.Equal(t, 1, st.A)
   118  				})
   119  				t.Run("not null", func(t *testing.T) {
   120  					st.A = -1
   121  					err := decCfg.UnmarshalFromString(`{"a":1}`, &st)
   122  					require.NoError(t, err)
   123  					require.Equal(t, 2, st.A)
   124  				})
   125  			})
   126  			t.Run("pointer", func(t *testing.T) {
   127  				st := struct {
   128  					A *int `json:"a"`
   129  				}{}
   130  				t.Run("not present", func(t *testing.T) {
   131  					v := 123
   132  					st.A = &v
   133  					err := decCfg.UnmarshalFromString(`{}`, &st)
   134  					require.NoError(t, err)
   135  					require.Equal(t, &v, st.A)
   136  				})
   137  				t.Run("null on not null", func(t *testing.T) {
   138  					v := 123
   139  					st.A = &v
   140  					err := decCfg.UnmarshalFromString(`{"a":null}`, &st)
   141  					require.NoError(t, err)
   142  					require.Nil(t, st.A)
   143  				})
   144  				t.Run("not null", func(t *testing.T) {
   145  					v := 123
   146  					st.A = &v
   147  					err := decCfg.UnmarshalFromString(`{"a":1}`, &st)
   148  					require.NoError(t, err)
   149  					require.NotNil(t, st.A)
   150  					require.Equal(t, 2, *st.A)
   151  				})
   152  			})
   153  		})
   154  	})
   155  	t.Run("ptr", func(t *testing.T) {
   156  		decCfg := NewDecoderConfig(&DecoderOption{
   157  			ValDecoders: map[reflect.Type]ValDecoder{
   158  				reflect.TypeOf((*int)(nil)): (*testPtrDecoder)(nil),
   159  			},
   160  			CaseSensitive: true,
   161  		})
   162  		t.Run("value", func(t *testing.T) {
   163  			t.Run("null", func(t *testing.T) {
   164  				var i *int
   165  				err := decCfg.UnmarshalFromString("null", &i)
   166  				require.NoError(t, err)
   167  				require.NotNil(t, i)
   168  				require.Equal(t, -1, *i)
   169  			})
   170  			t.Run("not null", func(t *testing.T) {
   171  				var i *int
   172  				err := decCfg.UnmarshalFromString("1", &i)
   173  				require.NoError(t, err)
   174  				require.NotNil(t, i)
   175  				require.Equal(t, 2, *i)
   176  			})
   177  		})
   178  		t.Run("struct", func(t *testing.T) {
   179  			t.Run("value", func(t *testing.T) {
   180  				st := struct {
   181  					A *int `json:"a"`
   182  				}{}
   183  				t.Run("null", func(t *testing.T) {
   184  					i := 123
   185  					st.A = &i
   186  					err := decCfg.UnmarshalFromString("null", &st)
   187  					require.NoError(t, err)
   188  					require.Equal(t, &i, st.A)
   189  				})
   190  				t.Run("not present", func(t *testing.T) {
   191  					i := 123
   192  					st.A = &i
   193  					err := decCfg.UnmarshalFromString(`{}`, &st)
   194  					require.NoError(t, err)
   195  					require.Equal(t, &i, st.A)
   196  				})
   197  				t.Run("present as null", func(t *testing.T) {
   198  					i := 123
   199  					st.A = &i
   200  					err := decCfg.UnmarshalFromString(`{"a":null}`, &st)
   201  					require.NoError(t, err)
   202  					require.NotNil(t, st.A)
   203  					require.Equal(t, -1, *st.A)
   204  				})
   205  				t.Run("present as not null", func(t *testing.T) {
   206  					i := 123
   207  					st.A = &i
   208  					err := decCfg.UnmarshalFromString(`{"a":1}`, &st)
   209  					require.NoError(t, err)
   210  					require.NotNil(t, st.A)
   211  					require.Equal(t, 2, *st.A)
   212  				})
   213  			})
   214  			t.Run("pointer", func(t *testing.T) {
   215  				st := struct {
   216  					A **int `json:"a"`
   217  				}{}
   218  				var v *int
   219  				st.A = &v
   220  				require.NotNil(t, st.A)
   221  				err := decCfg.UnmarshalFromString(`{"a":null}`, &st)
   222  				require.NoError(t, err)
   223  				require.Nil(t, st.A)
   224  			})
   225  		})
   226  	})
   227  	debug.FreeOSMemory()
   228  }