github.com/RevenueMonster/sqlike@v1.0.6/jsonb/decoder_test.go (about)

     1  package jsonb
     2  
     3  import (
     4  	"encoding/json"
     5  	"reflect"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/RevenueMonster/sqlike/reflext"
    10  	"github.com/stretchr/testify/require"
    11  	"golang.org/x/text/currency"
    12  	"golang.org/x/text/language"
    13  )
    14  
    15  type CustomString string
    16  
    17  func TestDecodeByte(t *testing.T) {
    18  	var (
    19  		dec = DefaultDecoder{}
    20  		r   *Reader
    21  		x   []byte
    22  		b   []byte
    23  		err error
    24  	)
    25  
    26  	v := reflext.ValueOf(&x).Elem()
    27  
    28  	r = NewReader([]byte(`""`))
    29  	err = dec.DecodeByte(r, v)
    30  	require.NoError(t, err)
    31  	require.Equal(t, make([]byte, 0), x)
    32  
    33  	r = NewReader([]byte(`null`))
    34  	err = dec.DecodeByte(r, v)
    35  	require.NoError(t, err)
    36  	require.Equal(t, []byte(nil), x)
    37  
    38  	b = []byte(`"VGhlIGlubGluZSB0YWJsZXMgYWJvdmUgYXJlIGlkZW50aWNhbCB0byB0aGUgZm9sbG93aW5nIHN0YW5kYXJkIHRhYmxlIGRlZmluaXRpb25zOg=="`)
    39  	r = NewReader(b)
    40  	err = dec.DecodeByte(r, v)
    41  	require.NoError(t, err)
    42  	require.Equal(t, []byte(`The inline tables above are identical to the following standard table definitions:`), x)
    43  }
    44  
    45  func TestDecodeLanguage(t *testing.T) {
    46  	var (
    47  		dec = DefaultDecoder{}
    48  		r   *Reader
    49  		// tag language.Tag
    50  		x   language.Tag
    51  		err error
    52  	)
    53  
    54  	v := reflext.ValueOf(&x).Elem()
    55  
    56  	// r = NewReader([]byte(`""`))
    57  	// err = dec.DecodeTime(r, v)
    58  	// require.NoError(t, err)
    59  	// require.Equal(t, time.Time{}, x)
    60  
    61  	{
    62  		r = NewReader([]byte(`"en"`))
    63  		err = dec.DecodeLanguage(r, v)
    64  		require.NoError(t, err)
    65  		require.Equal(t, language.English, x)
    66  	}
    67  }
    68  
    69  func TestCurrency(t *testing.T) {
    70  	var (
    71  		dec = DefaultDecoder{registry: buildDefaultRegistry()}
    72  		r   *Reader
    73  		x   currency.Unit
    74  		err error
    75  	)
    76  
    77  	v := reflext.ValueOf(&x).Elem()
    78  
    79  	t.Run("Decode with null", func(ti *testing.T) {
    80  		r = NewReader([]byte(`null`))
    81  		err = dec.DecodeCurrency(r, v)
    82  		require.NoError(t, err)
    83  		require.Equal(t, currency.Unit{}, x)
    84  	})
    85  
    86  	t.Run("Decode with value", func(ti *testing.T) {
    87  		r = NewReader([]byte(`"USD"`))
    88  		err = dec.DecodeCurrency(r, v)
    89  		require.NoError(t, err)
    90  		require.Equal(t, currency.USD, x)
    91  	})
    92  
    93  	t.Run("Decode with invalid value", func(ti *testing.T) {
    94  		r = NewReader([]byte(`"USDT"`))
    95  		err = dec.DecodeCurrency(r, v)
    96  		require.Error(t, err)
    97  	})
    98  }
    99  
   100  func TestDecodeTime(t *testing.T) {
   101  	var (
   102  		dec = DefaultDecoder{}
   103  		r   *Reader
   104  		dt  time.Time
   105  		x   time.Time
   106  		err error
   107  	)
   108  
   109  	v := reflext.ValueOf(&x).Elem()
   110  
   111  	r = NewReader([]byte(`""`))
   112  	err = dec.DecodeTime(r, v)
   113  	require.NoError(t, err)
   114  	require.Equal(t, time.Time{}, x)
   115  
   116  	dt, _ = time.Parse("2006-01-02", "2018-01-02")
   117  	r = NewReader([]byte(`"2018-01-02"`))
   118  	err = dec.DecodeTime(r, v)
   119  	require.NoError(t, err)
   120  	require.Equal(t, dt, x)
   121  
   122  	dt, _ = time.Parse("2006-01-02 15:04:05", "2018-01-02 13:58:26")
   123  	r = NewReader([]byte(`"2018-01-02 13:58:26"`))
   124  	err = dec.DecodeTime(r, v)
   125  	require.NoError(t, err)
   126  	require.Equal(t, dt, x)
   127  
   128  	t.Run("Decode Time w invalid format", func(it *testing.T) {
   129  		r = NewReader([]byte(`"2018-01-02 13:65:66"`))
   130  		err = dec.DecodeTime(r, v)
   131  		require.Error(it, err)
   132  
   133  		r = NewReader([]byte(`2018-01-02 13:65:66"`))
   134  		err = dec.DecodeTime(r, v)
   135  		require.Error(it, err)
   136  
   137  		r = NewReader([]byte(`"2018-01-02 13:65:66`))
   138  		err = dec.DecodeTime(r, v)
   139  		require.Error(it, err)
   140  
   141  		r = NewReader([]byte(``))
   142  		err = dec.DecodeTime(r, v)
   143  		require.Error(it, err)
   144  	})
   145  
   146  }
   147  
   148  func TestDecodeJSONRaw(t *testing.T) {
   149  	var (
   150  		dec = DefaultDecoder{registry: buildDefaultRegistry()}
   151  		r   *Reader
   152  		x   json.RawMessage
   153  		err error
   154  	)
   155  
   156  	v := reflext.ValueOf(&x).Elem()
   157  
   158  	t.Run("Decode with null", func(ti *testing.T) {
   159  		r = NewReader([]byte(`null`))
   160  		err = dec.DecodeJSONRaw(r, v)
   161  		require.NoError(t, err)
   162  		require.Equal(t, json.RawMessage(`null`), x)
   163  	})
   164  
   165  	t.Run("Decode with number", func(ti *testing.T) {
   166  		r = NewReader([]byte(`98`))
   167  		err = dec.DecodeJSONRaw(r, v)
   168  		require.NoError(t, err)
   169  		require.Equal(t, json.RawMessage(`98`), x)
   170  	})
   171  }
   172  
   173  func TestDecodeJSONNumber(t *testing.T) {
   174  	var (
   175  		dec = DefaultDecoder{registry: buildDefaultRegistry()}
   176  		r   *Reader
   177  		x   json.Number
   178  		err error
   179  	)
   180  
   181  	v := reflext.ValueOf(&x).Elem()
   182  
   183  	t.Run("Decode with null", func(ti *testing.T) {
   184  		r = NewReader([]byte(`null`))
   185  		err = dec.DecodeJSONNumber(r, v)
   186  		require.NoError(t, err)
   187  		require.Equal(t, json.Number("0"), x)
   188  	})
   189  
   190  	t.Run("Decode with position integer", func(ti *testing.T) {
   191  		r = NewReader([]byte(`88`))
   192  		err = dec.DecodeJSONNumber(r, v)
   193  		require.NoError(t, err)
   194  		require.Equal(t, json.Number("88"), x)
   195  		require.Equal(t, "88", x.String())
   196  		i64, _ := x.Int64()
   197  		require.Equal(t, int64(88), i64)
   198  		f64, _ := x.Float64()
   199  		require.Equal(t, float64(88), f64)
   200  	})
   201  
   202  	t.Run("Decode json.Number w invalid value", func(ti *testing.T) {
   203  		r = NewReader([]byte(`hsdjdkd`))
   204  		err = dec.DecodeJSONNumber(r, v)
   205  		require.Error(t, err)
   206  
   207  		// r = NewReader([]byte(`10.3a`))
   208  		// err = dec.DecodeJSONNumber(r, v)
   209  		// require.Error(t, err)
   210  	})
   211  }
   212  
   213  func TestDecodeMap(t *testing.T) {
   214  	var (
   215  		dec = DefaultDecoder{registry: buildDefaultRegistry()}
   216  		r   *Reader
   217  		x   map[string]interface{}
   218  		err error
   219  	)
   220  
   221  	v := reflext.ValueOf(&x).Elem()
   222  
   223  	t.Run("Decode with null", func(ti *testing.T) {
   224  		r = NewReader([]byte(`null`))
   225  		err = dec.DecodeMap(r, v)
   226  		require.NoError(t, err)
   227  		require.Equal(t, map[string]interface{}(nil), x)
   228  	})
   229  
   230  	t.Run("Decode with empty object", func(ti *testing.T) {
   231  		r = NewReader([]byte(`{}`))
   232  		err = dec.DecodeMap(r, v)
   233  		require.NoError(t, err)
   234  		require.Equal(t, make(map[string]interface{}), x)
   235  	})
   236  
   237  	t.Run("Decode to map<string,interface{}>", func(ti *testing.T) {
   238  		r = NewReader([]byte(`
   239  		{
   240  			"a":"123", 
   241  			"b":   108213312, 
   242  			"c": true, 
   243  			"d": "alSLKaj28173-021@#$%^&*\"",
   244  			"e": 0.3127123
   245  		}`))
   246  		err = dec.DecodeMap(r, v)
   247  		require.NoError(t, err)
   248  		require.Equal(t, map[string]interface{}{
   249  			"a": "123",
   250  			"b": float64(108213312),
   251  			"c": true,
   252  			"d": `alSLKaj28173-021@#$%^&*"`,
   253  			"e": float64(0.3127123),
   254  		}, x)
   255  
   256  	})
   257  
   258  	t.Run("Decode to map<string,string>", func(ti *testing.T) {
   259  		r = NewReader([]byte(`
   260  		{
   261  			"number":      "1234567890", 
   262  			"b":"abcdefghijklmnopqrstuvwxyz",
   263  			"emoji": "๐Ÿ˜€ ๐Ÿ˜ ๐Ÿ˜‚ ๐Ÿคฃ ๐Ÿ˜ƒ ๐Ÿ˜„ ๐Ÿ˜… ๐Ÿ˜† ๐Ÿ˜‰ ๐Ÿ˜Š",
   264  			"japanese": "็ฆๅฒกๅธ‚็พŽ่ก“้คจใงๅคœ้–“้–‹้คจใ‚นใ‚ฟใƒผใƒˆ๏ผ7ๆœˆ๏ฝž10ๆœˆใฎ้‡‘ๆ›œๆ—ฅใจๅœŸๆ›œๆ—ฅใฏ20ๆ™‚ใพใงๅปถ้•ท้–‹้คจ"
   265  		}`))
   266  		m := make(map[string]string)
   267  		v := reflect.ValueOf(&m)
   268  		err = dec.DecodeMap(r, v.Elem())
   269  		require.NoError(ti, err)
   270  		require.Equal(ti, map[string]string{
   271  			"number":   "1234567890",
   272  			"b":        "abcdefghijklmnopqrstuvwxyz",
   273  			"emoji":    "๐Ÿ˜€ ๐Ÿ˜ ๐Ÿ˜‚ ๐Ÿคฃ ๐Ÿ˜ƒ ๐Ÿ˜„ ๐Ÿ˜… ๐Ÿ˜† ๐Ÿ˜‰ ๐Ÿ˜Š",
   274  			"japanese": "็ฆๅฒกๅธ‚็พŽ่ก“้คจใงๅคœ้–“้–‹้คจใ‚นใ‚ฟใƒผใƒˆ๏ผ7ๆœˆ๏ฝž10ๆœˆใฎ้‡‘ๆ›œๆ—ฅใจๅœŸๆ›œๆ—ฅใฏ20ๆ™‚ใพใงๅปถ้•ท้–‹้คจ",
   275  		}, m)
   276  	})
   277  
   278  	t.Run("Decode to map<string,bool>", func(ti *testing.T) {
   279  		r = NewReader([]byte(`
   280  		{
   281  			"true":     true, 
   282  			"false": false
   283  		}`))
   284  		m := make(map[string]bool)
   285  		v := reflect.ValueOf(&m)
   286  		err = dec.DecodeMap(r, v.Elem())
   287  		require.NoError(ti, err)
   288  		require.Equal(ti, map[string]bool{
   289  			"true":  true,
   290  			"false": false,
   291  		}, m)
   292  	})
   293  
   294  	t.Run("Decode to map<string,int>", func(ti *testing.T) {
   295  		r = NewReader([]byte(`
   296  		{
   297  			"minus-one": -1,
   298  			"negative": -31231237,
   299  			"one":      1, 
   300  			"two":2,
   301  			"eleven": 11,
   302  			"hundred": 100
   303  		}`))
   304  		m := make(map[string]int)
   305  		v := reflect.ValueOf(&m)
   306  		err = dec.DecodeMap(r, v.Elem())
   307  		require.NoError(ti, err)
   308  		require.Equal(ti, map[string]int{
   309  			"minus-one": -1,
   310  			"negative":  -31231237,
   311  			"one":       1,
   312  			"two":       2,
   313  			"eleven":    11,
   314  			"hundred":   100,
   315  		}, m)
   316  	})
   317  
   318  	t.Run("Decode to map<string,uint8>", func(ti *testing.T) {
   319  		r = NewReader([]byte(`
   320  		{
   321  			"one":      1, 
   322  			"two":2,
   323  			"eleven": 11,
   324  			"hundred": 100
   325  		}`))
   326  		m := make(map[string]uint8)
   327  		v := reflect.ValueOf(&m)
   328  		err = dec.DecodeMap(r, v.Elem())
   329  		require.NoError(ti, err)
   330  		require.Equal(ti, map[string]uint8{
   331  			"one":     1,
   332  			"two":     2,
   333  			"eleven":  11,
   334  			"hundred": 100,
   335  		}, m)
   336  	})
   337  
   338  	t.Run("Decode to map<string,float32>", func(ti *testing.T) {
   339  		r = NewReader([]byte(`
   340  		{
   341  			"minus-one": -1,
   342  			"negative":  -31231237,
   343  			"one":      1, 
   344  			"two":2,
   345  			"eleven": 11,
   346  			"hundred": 100,
   347  			"number":    3123123799213,
   348  		}`))
   349  		m := make(map[string]float32)
   350  		v := reflect.ValueOf(&m)
   351  		err = dec.DecodeMap(r, v.Elem())
   352  		require.NoError(ti, err)
   353  		require.Equal(ti, map[string]float32{
   354  			"minus-one": -1,
   355  			"negative":  -31231237,
   356  			"one":       1,
   357  			"two":       2,
   358  			"eleven":    11,
   359  			"hundred":   100,
   360  			"number":    3123123799213,
   361  		}, m)
   362  	})
   363  
   364  	t.Run("Decode to map<string,float64>", func(ti *testing.T) {
   365  		r = NewReader([]byte(`
   366  		{
   367  			"minus-one": -1,
   368  			"negative":  -3123123799213,
   369  			"one":      1, 
   370  			"two":2,
   371  			"eleven": 11,
   372  			"hundred": 100,
   373  			"number":    3123123799213,
   374  		}`))
   375  		m := make(map[string]float64)
   376  		v := reflect.ValueOf(&m)
   377  		err = dec.DecodeMap(r, v.Elem())
   378  		require.NoError(ti, err)
   379  		require.Equal(ti, map[string]float64{
   380  			"minus-one": -1,
   381  			"negative":  -3123123799213,
   382  			"one":       1,
   383  			"two":       2,
   384  			"eleven":    11,
   385  			"hundred":   100,
   386  			"number":    3123123799213,
   387  		}, m)
   388  	})
   389  
   390  	t.Run("Decode to map<string,interface{}>", func(ti *testing.T) {
   391  		r = NewReader([]byte(`
   392  		{
   393  			"negative": -183,
   394  			"string": "textasjdhasljdlasjkdjlsa:'dasdas",
   395  			"number":    3123123799213,
   396  			"nested": {
   397  				"k": {
   398  					"bool": true,
   399  					"no": 10,
   400  					"string": "๐Ÿ˜€๐Ÿ˜๐Ÿ˜‚"
   401  				}
   402  			}
   403  		}`))
   404  		m := make(map[string]interface{})
   405  		v := reflect.ValueOf(&m)
   406  		err = dec.DecodeMap(r, v.Elem())
   407  		require.NoError(ti, err)
   408  		require.Equal(ti, map[string]interface{}{
   409  			"negative": float64(-183),
   410  			"string":   "textasjdhasljdlasjkdjlsa:'dasdas",
   411  			"number":   float64(3123123799213),
   412  			"nested": map[string]interface{}{
   413  				"k": map[string]interface{}{
   414  					"bool":   true,
   415  					"no":     float64(10),
   416  					"string": "๐Ÿ˜€๐Ÿ˜๐Ÿ˜‚",
   417  				},
   418  			},
   419  		}, m)
   420  	})
   421  
   422  	t.Run("Decode to map[CustomString]*string", func(ti *testing.T) {
   423  		var m map[CustomString]*string
   424  
   425  		r = NewReader([]byte(`
   426  		{
   427  			"0": "zero",
   428  			"1": "one",
   429  			"2": "two",
   430  			"3": "three"
   431  		}`))
   432  
   433  		v := reflect.ValueOf(&m)
   434  		err = dec.DecodeMap(r, v.Elem())
   435  		require.NoError(ti, err)
   436  		zero, one, two, three := "zero", "one", "two", "three"
   437  		require.Equal(t, map[CustomString]*string{
   438  			CustomString("0"): &zero,
   439  			CustomString("1"): &one,
   440  			CustomString("2"): &two,
   441  			CustomString("3"): &three,
   442  		}, m)
   443  	})
   444  
   445  	t.Run("Decode with unsupported data type", func(ti *testing.T) {
   446  		var mx map[*CustomString]string
   447  		r = NewReader([]byte(`
   448  		{
   449  			"0": "zero",
   450  			"1": "one",
   451  			"2": "two",
   452  			"3": "three"
   453  		}`))
   454  		v = reflect.ValueOf(&mx)
   455  		err = dec.DecodeMap(r, v.Elem())
   456  		require.Error(ti, err)
   457  	})
   458  
   459  }
   460  
   461  func TestDecodeArray(t *testing.T) {
   462  	var (
   463  		err error
   464  	)
   465  
   466  	t.Run("Decode to [2]string", func(ti *testing.T) {
   467  		arr := [2]string{}
   468  		err = Unmarshal([]byte(`["test", "abc", "ddd"]`), &arr)
   469  		require.Error(ti, err)
   470  
   471  		err = Unmarshal([]byte(`["ไบฌ้ƒฝ็€็‰ฉใƒฌใƒณใ‚ฟใƒซๅคข้คจ", "aBcdEfgHiJklmnO"]`), &arr)
   472  		require.NoError(ti, err)
   473  		require.ElementsMatch(ti, [...]string{
   474  			"ไบฌ้ƒฝ็€็‰ฉใƒฌใƒณใ‚ฟใƒซๅคข้คจ",
   475  			"aBcdEfgHiJklmnO",
   476  		}, arr)
   477  	})
   478  
   479  	t.Run("Decode to []int", func(ti *testing.T) {
   480  		arr := []int{}
   481  		err = Unmarshal([]byte(`[1, "xdd", 3]`), &arr)
   482  		require.Error(ti, err)
   483  
   484  		err = Unmarshal([]byte(`[1, 88, 3, -1992, 9999]`), &arr)
   485  		require.NoError(ti, err)
   486  		require.ElementsMatch(t, []int{1, 88, 3, -1992, 9999}, arr)
   487  	})
   488  
   489  	t.Run("Decode to []struct{}", func(it *testing.T) {
   490  		type Region struct {
   491  			DialingCode int
   492  			CountryCode string
   493  		}
   494  
   495  		type Contact struct {
   496  			Name        string
   497  			LangCode    language.Tag
   498  			PhoneNumber string
   499  			IsPrimary   bool
   500  			Region      Region
   501  		}
   502  
   503  		type Address struct {
   504  			Remark         string
   505  			Address        string
   506  			Contact        Contact
   507  			FloorNumber    string
   508  			BuildingNumber string
   509  			EntranceNumber string
   510  		}
   511  
   512  		addrs := []Address{}
   513  		b := []byte(`{hsh:""}`)
   514  		err = Unmarshal(b, &addrs)
   515  		require.Error(t, err)
   516  
   517  		b = []byte(`[
   518  			{
   519  				"Remark": "One Utama, 1 UTAMA SHOPPING CENTRE,  LEBUH BANDAR UTAMA,  BANDAR UTAMA",
   520  				"Address": "1 UTAMA SHOPPING CENTRE,  LEBUH BANDAR UTAMA,  BANDAR UTAMA, KOTA DAMANSARA PETALING JAYA, 47800, Petaling Jaya, Selangor, Malaysia",
   521  				"Contact": {
   522  					"Name": "One Utama",
   523  					"PhoneNumber": "60176473298"
   524  				},
   525  				"FloorNumber": "",
   526  				"BuildingNumber": "",
   527  				"EntranceNumber": ""
   528  			},
   529  			{
   530  				"Remark": "",
   531  				"Address": "Gugusan Melur, Kota Damansara, 47810, Petaling Jaya, Selangor, Malaysia",
   532  				"Contact": {
   533  					"Name": "Mohamed Yussuf",
   534  					"PhoneNumber": "60176473298",
   535  					"IsPrimary": true,
   536  					"Region": {
   537  						"DialingCode": 60,
   538  						"CountryCode": "MY"
   539  					}
   540  				},
   541  				"FloorNumber": "",
   542  				"BuildingNumber": "",
   543  				"EntranceNumber": ""
   544  			}
   545  		]`)
   546  
   547  		addrs = []Address{} // reset address
   548  		err = Unmarshal(b, &addrs)
   549  		require.NoError(t, err)
   550  
   551  		require.ElementsMatch(t, []Address{
   552  			{
   553  				Address: "1 UTAMA SHOPPING CENTRE,  LEBUH BANDAR UTAMA,  BANDAR UTAMA, KOTA DAMANSARA PETALING JAYA, 47800, Petaling Jaya, Selangor, Malaysia",
   554  				Remark:  "One Utama, 1 UTAMA SHOPPING CENTRE,  LEBUH BANDAR UTAMA,  BANDAR UTAMA",
   555  				Contact: Contact{
   556  					Name:        "One Utama",
   557  					PhoneNumber: "60176473298",
   558  				},
   559  			},
   560  			{
   561  				Address: "Gugusan Melur, Kota Damansara, 47810, Petaling Jaya, Selangor, Malaysia",
   562  				Contact: Contact{
   563  					Name:        "Mohamed Yussuf",
   564  					PhoneNumber: "60176473298",
   565  					IsPrimary:   true,
   566  					Region: Region{
   567  						DialingCode: 60,
   568  						CountryCode: "MY",
   569  					},
   570  				},
   571  			},
   572  		}, addrs)
   573  	})
   574  }