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

     1  package jsonb
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"io/ioutil"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/RevenueMonster/sqlike/types"
    11  	"github.com/google/uuid"
    12  	"github.com/stretchr/testify/require"
    13  	"golang.org/x/text/currency"
    14  	"golang.org/x/text/language"
    15  )
    16  
    17  type User struct {
    18  	Name  string
    19  	Email string
    20  	Age   int
    21  	UUID  uuid.UUID
    22  }
    23  
    24  type ptrStruct struct {
    25  	PtrStr          *string
    26  	PtrByte         *[]byte
    27  	PtrBool         *bool
    28  	PtrInt          *int
    29  	PtrInt8         *int8
    30  	PtrInt16        *int16
    31  	PtrInt32        *int32
    32  	PtrInt64        *int64
    33  	PtrUint         *uint
    34  	PtrUint8        *uint8
    35  	PtrUint16       *uint16
    36  	PtrUint32       *uint32
    37  	PtrUint64       *uint64
    38  	PtrFloat32      *float32
    39  	PtrFloat64      *float64
    40  	PtrJSONRaw      *json.RawMessage
    41  	PtrJSONNumber   *json.Number
    42  	PtrStrSlice     *[]string
    43  	PtrIntSlice     *[]int
    44  	PtrUintSlice    *[]uint
    45  	PtrF32Slice     *[]float32
    46  	PtrF64Slice     *[]float64
    47  	PtrLanguageTag  *language.Tag
    48  	PtrCurrencyUnit *currency.Unit
    49  	PtrUUID         *uuid.UUID
    50  	PtrTime         *time.Time
    51  	PtrStruct       *struct {
    52  		Nested string
    53  	}
    54  }
    55  
    56  type testStruct struct {
    57  	Str        string
    58  	UUID       *****uuid.UUID
    59  	BigDecimal float64
    60  	SymbolStr  string
    61  	EscapeStr  string
    62  	StrSlice   []string
    63  	Users      []User
    64  	Nested     struct {
    65  		NilKey         *types.Key
    66  		MultiNilPtrKey ******types.Key
    67  		Key            *types.Key
    68  		MultiPtr       ***string
    69  		Security       struct {
    70  			PrivateKey []byte
    71  		}
    72  		Test   string
    73  		Test2  string
    74  		Nested struct {
    75  			Deep struct {
    76  				Value float64 `sqlike:"value"`
    77  			} `sqlike:"deep1"`
    78  			YOLO string `sqlike:"deep2"`
    79  		} `sqlike:"nested"`
    80  	}
    81  	EmptyStruct struct{}
    82  	Integer     int
    83  	Bool        bool
    84  }
    85  
    86  type customKey struct {
    87  	value string
    88  }
    89  
    90  func (c *customKey) UnmarshalText(b []byte) error {
    91  	*c = customKey{value: string(b)}
    92  	return nil
    93  }
    94  
    95  func TestUnmarshal(t *testing.T) {
    96  	var (
    97  		strval       = `hello world !!!!!!`
    98  		symbolstrval = `\n\t\t\t<html>\n\t\t\t\t<div>Hello World</div>\n\t\t\t</html>\n\t\t\ttesting with !@#$%^&*(_)()()_()_((*??D|}A||||\\\\))\n\t\t`
    99  		byteval      = []byte(`LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDWFFJQkFBS0JnUUMrYUlTemtOdXFiZmdxWW9IYW1iS0dyaEF6UnV0dWYydWFzOUJIeXllUFJUdUk5ZVdwCnJHY3lRZlhPVlh2OGJBZVMxK2tIS0MvK1ZDTk9EbGZBTFlQWVVZa053eHVvRnFMbU1SR3E1MzMwSEVLSUpySDcKSUU5aUs0QUVZL3h5WjBTUEp5ZkNnQ2ZaeGtJTmpacWFoSS8rVWxrL1BmdWwyaEQ0ZTNUZVpGTm5HUUlEQVFBQgpBb0dBSHpOYlExMWlVV3dSdFVoTkJQZ1lnKzh6NG1NbG93YW9LRUo4eDdibmRaZWZxTks2WG5KTXVyU0tSZFJHCks5ZTc2ZmtOUzBudmkxcFlLcXM0LzltMWQ4Mk9XdmtDeXZvR3pmRXdyNGJ6bVBBZjdkczVkWElhb29wbWV4WWwKbFpsSmtuMDhWNFJmOWc4RFEyNFRsb3BpZ3RrSzY5UktRSzFHaHVyV1A4UjVxeTBDUVFEZ3dxcGVKZFF5RUdaYgpQUElJN2ZsSUVDRjlQNnNVc1ovNW40cEhNNmg2N0dOdGU1cEx4bDkzOXYybVhaN09aSUZHQU1rUmNDL1ZIK3c4Cm5oaytaNE9yQWtFQTJOK01oOWRpN1YreldaNUNIWXBWTHM5Qi9xOVl3YjFCNjN0UnZUbG9QSnFqTHc1NDUzZUUKbEs0ZnJSaVhXbEhLaUpLYlBOTU1ZUVkyTVRrcEQ2dDhTd0pCQUlkU2JRVFdQZFlPcmJITkZlUnVjeUlDSkVlbQpwN2lENFUrSDBOZGhzTlNoc3BOZVVkM0JpQVZRZmhOR1ZyRHBMalFaa1BXZzJBdTNkcUpnaGM1ZXdKVUNRQUVFCkV4RnoxZGZNMGZkQ2dZYkg1aHhCQmtzZUlTbFBMS2JndmdKSDZaQVhIVnFVRThicHpXb3c0cDhaOVdPTDdJbjEKUGRyc0ZpdkNMckRPVnIzbkRMOENRUURKSENwSEVFNTc0ckpzblJNYk5rR0F5dmZheW9MeElhVUF5WXovaGxrMgpzQ0wzb3BsdDNYM0tjYzV1MkRISVFsZTdGM1M4Wmp4REZMSVRrbnJ4QS9UVgotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==`)
   100  		nullval      = []byte(`null`)
   101  	)
   102  
   103  	var (
   104  		pk  []byte
   105  		b   []byte
   106  		err error
   107  	)
   108  
   109  	t.Run("Unmarshal RawMessage", func(it *testing.T) {
   110  		var (
   111  			b = []byte(`{
   112  				"Raw": {
   113  					"Title": "Header",
   114  					"Body": {}
   115  				},
   116  				"Nested" : {
   117  					"DeepNested" : {
   118  						"RawObject" : {
   119  							"Name" : "john",
   120  							"Email" : "john@hotmail.com",
   121  							"Emoji":  " πŸ˜† πŸ˜‰ 😊 ",
   122  							"Age" : 28
   123  						},
   124  						"RawStr" : "hello world!",
   125  						"RawNumber": 189202.882
   126  					}
   127  				}
   128  			}`)
   129  			o struct {
   130  				Raw    json.RawMessage
   131  				Nested struct {
   132  					DeepNested struct {
   133  						RawObject json.RawMessage
   134  						RawStr    json.RawMessage
   135  						RawNumber json.RawMessage
   136  					}
   137  				}
   138  			}
   139  		)
   140  
   141  		err = Unmarshal(b, &o)
   142  		require.NoError(it, err)
   143  		require.Equal(it, json.RawMessage(`{"Title":"Header","Body":{}}`), o.Raw)
   144  		require.Equal(it, json.RawMessage(`{"Name":"john","Email":"john@hotmail.com","Emoji":" πŸ˜† πŸ˜‰ 😊 ","Age":28}`), o.Nested.DeepNested.RawObject)
   145  		require.Equal(it, json.RawMessage(`"hello world!"`), o.Nested.DeepNested.RawStr)
   146  		require.Equal(it, json.RawMessage(`189202.882`), o.Nested.DeepNested.RawNumber)
   147  		require.Equal(it, json.RawMessage(`"hello world!"`), o.Nested.DeepNested.RawStr)
   148  	})
   149  
   150  	{
   151  		pk, err = ioutil.ReadFile("./../examples/pk.pem")
   152  		require.NoError(t, err)
   153  		b, err = base64.StdEncoding.DecodeString(string(byteval))
   154  		require.NoError(t, err)
   155  		require.Equal(t, b, pk)
   156  	}
   157  
   158  	t.Run("Unmarshal UUID", func(it *testing.T) {
   159  		var uid uuid.UUID
   160  		err = Unmarshal([]byte(`"4c03d1de-645b-40d2-9ed5-12bb537a602e"`), &uid)
   161  		require.NoError(t, err)
   162  		require.Equal(t, uuid.MustParse("4c03d1de-645b-40d2-9ed5-12bb537a602e"), uid)
   163  
   164  		var ptruid *****uuid.UUID
   165  		err = Unmarshal([]byte(`"4c03d1de-645b-40d2-9ed5-12bb537a602e"`), &ptruid)
   166  		require.NoError(t, err)
   167  		require.NotNil(t, ptruid)
   168  		require.Equal(t, uuid.MustParse("4c03d1de-645b-40d2-9ed5-12bb537a602e"), *****ptruid)
   169  
   170  		var nilUUID *uuid.UUID
   171  		err = Unmarshal([]byte(`null`), &nilUUID)
   172  		require.NoError(t, err)
   173  		require.Nil(t, nilUUID)
   174  	})
   175  
   176  	t.Run("Unmarshal String", func(it *testing.T) {
   177  		var (
   178  			addrptr *string
   179  			nilptr  *string
   180  		)
   181  
   182  		err = Unmarshal([]byte(`null`), &addrptr)
   183  		require.NoError(t, err)
   184  		require.Equal(t, nilptr, addrptr)
   185  
   186  		var str string
   187  		err = Unmarshal([]byte(`"`+strval+`"`), &str)
   188  		require.Equal(it, strval, str)
   189  		require.NoError(t, err)
   190  
   191  		output := `
   192  			<html>
   193  				<div>Hello World</div>
   194  			</html>
   195  			testing with !@#$%^&*(_)()()_()_((*??D|}A||||\\))
   196  		`
   197  
   198  		var symbolstr string
   199  		err = Unmarshal([]byte(`"`+symbolstrval+`"`), &symbolstr)
   200  		require.NoError(t, err)
   201  		require.Equal(it, output, symbolstr)
   202  
   203  		err = Unmarshal(nullval, &str)
   204  		require.NoError(t, err)
   205  		require.Equal(it, "", str)
   206  
   207  		var uinitstr *string
   208  		err = Unmarshal([]byte(`null`), uinitstr)
   209  		require.Error(t, err)
   210  
   211  		err = Unmarshal([]byte(`null`), nil)
   212  		require.Error(t, err)
   213  	})
   214  
   215  	t.Run("Unmarshal Boolean", func(it *testing.T) {
   216  		var flag bool
   217  		err = Unmarshal([]byte(`true`), &flag)
   218  		require.NoError(t, err)
   219  		require.Equal(it, true, flag)
   220  
   221  		err = Unmarshal([]byte(`false`), &flag)
   222  		require.NoError(t, err)
   223  		require.Equal(it, false, flag)
   224  
   225  		err = Unmarshal(nullval, &flag)
   226  		require.NoError(it, err)
   227  		require.Equal(it, false, flag)
   228  	})
   229  
   230  	t.Run("Unmarshal Integer", func(it *testing.T) {
   231  		var (
   232  			i8  int8
   233  			i16 int16
   234  			i32 int32
   235  			i64 int64
   236  			i   int
   237  		)
   238  
   239  		err = Unmarshal([]byte(`10`), &i8)
   240  		require.NoError(t, err)
   241  		require.Equal(it, int8(10), i8)
   242  
   243  		err = Unmarshal([]byte(`-10`), &i8)
   244  		require.NoError(t, err)
   245  		require.Equal(it, int8(-10), i8)
   246  
   247  		err = Unmarshal(nullval, &i8)
   248  		require.NoError(t, err)
   249  		require.Equal(it, int8(0), i8)
   250  
   251  		err = Unmarshal([]byte(`128`), &i16)
   252  		require.NoError(t, err)
   253  		require.Equal(it, int16(128), i16)
   254  
   255  		err = Unmarshal([]byte(`-128`), &i16)
   256  		require.NoError(t, err)
   257  		require.Equal(it, int16(-128), i16)
   258  
   259  		err = Unmarshal(nullval, &i16)
   260  		require.NoError(t, err)
   261  		require.Equal(it, int16(0), i16)
   262  
   263  		err = Unmarshal([]byte(`1354677198`), &i32)
   264  		require.NoError(t, err)
   265  		require.Equal(it, int32(1354677198), i32)
   266  
   267  		err = Unmarshal([]byte(`-1354677198`), &i32)
   268  		require.NoError(t, err)
   269  		require.Equal(it, int32(-1354677198), i32)
   270  
   271  		err = Unmarshal(nullval, &i32)
   272  		require.NoError(t, err)
   273  		require.Equal(it, int32(0), i32)
   274  
   275  		err = Unmarshal([]byte(`7354673213123121983`), &i64)
   276  		require.NoError(t, err)
   277  		require.Equal(it, int64(7354673213123121983), i64)
   278  
   279  		err = Unmarshal([]byte(`-7354673213123121983`), &i64)
   280  		require.NoError(t, err)
   281  		require.Equal(it, int64(-7354673213123121983), i64)
   282  
   283  		err = Unmarshal(nullval, &i64)
   284  		require.NoError(t, err)
   285  		require.Equal(it, int64(0), i64)
   286  
   287  		err = Unmarshal([]byte(`1354677198`), &i)
   288  		require.NoError(t, err)
   289  		require.Equal(it, int(1354677198), i)
   290  
   291  		err = Unmarshal([]byte(`-1354677198`), &i)
   292  		require.NoError(t, err)
   293  		require.Equal(it, int(-1354677198), i)
   294  
   295  		err = Unmarshal(nullval, &i)
   296  		require.NoError(t, err)
   297  		require.Equal(it, int(0), i)
   298  	})
   299  
   300  	t.Run("Unmarshal Unsigned Integer", func(it *testing.T) {
   301  		var (
   302  			ui8  uint8
   303  			ui16 uint16
   304  			ui32 uint32
   305  			ui64 uint64
   306  			ui   uint
   307  		)
   308  
   309  		err = Unmarshal([]byte(`10`), &ui8)
   310  		require.NoError(t, err)
   311  		require.Equal(it, uint8(10), ui8)
   312  
   313  		err = Unmarshal([]byte(`-10`), &ui8)
   314  		require.Error(t, err)
   315  
   316  		err = Unmarshal(nullval, &ui8)
   317  		require.NoError(t, err)
   318  		require.Equal(it, uint8(0), ui8)
   319  
   320  		err = Unmarshal([]byte(`128`), &ui16)
   321  		require.NoError(t, err)
   322  		require.Equal(it, uint16(128), ui16)
   323  
   324  		err = Unmarshal([]byte(`-128`), &ui16)
   325  		require.Error(t, err)
   326  
   327  		err = Unmarshal(nullval, &ui16)
   328  		require.NoError(t, err)
   329  		require.Equal(it, uint16(0), ui16)
   330  
   331  		err = Unmarshal([]byte(`1354677198`), &ui32)
   332  		require.NoError(t, err)
   333  		require.Equal(it, uint32(1354677198), ui32)
   334  
   335  		err = Unmarshal([]byte(`-1354677198`), &ui32)
   336  		require.Error(t, err)
   337  
   338  		err = Unmarshal(nullval, &ui32)
   339  		require.NoError(t, err)
   340  		require.Equal(it, uint32(0), ui32)
   341  
   342  		err = Unmarshal([]byte(`7354673213123121983`), &ui64)
   343  		require.NoError(t, err)
   344  		require.Equal(it, uint64(7354673213123121983), ui64)
   345  
   346  		err = Unmarshal([]byte(`-7354673213123121983`), &ui64)
   347  		require.Error(t, err)
   348  
   349  		err = Unmarshal(nullval, &ui64)
   350  		require.NoError(t, err)
   351  		require.Equal(it, uint64(0), ui64)
   352  
   353  		err = Unmarshal([]byte(`1354677198`), &ui)
   354  		require.NoError(t, err)
   355  		require.Equal(it, uint(1354677198), ui)
   356  
   357  		err = Unmarshal([]byte(`-1354677198`), &ui)
   358  		require.Error(t, err)
   359  
   360  		err = Unmarshal(nullval, &ui)
   361  		require.NoError(t, err)
   362  		require.Equal(it, uint(0), ui)
   363  	})
   364  
   365  	t.Run("Unmarshal Float", func(it *testing.T) {
   366  		var (
   367  			f32 float32
   368  			f64 float64
   369  		)
   370  
   371  		err = Unmarshal([]byte(`10`), &f32)
   372  		require.NoError(t, err)
   373  		require.Equal(it, float32(10), f32)
   374  
   375  		err = Unmarshal([]byte(`10.32`), &f32)
   376  		require.NoError(t, err)
   377  		require.Equal(it, float32(10.32), f32)
   378  
   379  		err = Unmarshal([]byte(`-882.3261239`), &f32)
   380  		require.NoError(t, err)
   381  		require.Equal(it, float32(-882.3261239), f32)
   382  
   383  		err = Unmarshal([]byte(`-128.32128392`), &f64)
   384  		require.NoError(t, err)
   385  		require.Equal(it, float64(-128.32128392), f64)
   386  
   387  		err = Unmarshal([]byte(`10.32128392`), &f64)
   388  		require.NoError(t, err)
   389  		require.Equal(it, float64(10.32128392), f64)
   390  	})
   391  
   392  	t.Run("Unmarshal Byte", func(it *testing.T) {
   393  		b = []byte(`"` + string(byteval) + `"`)
   394  		var bytea []byte
   395  		err = Unmarshal(b, &bytea)
   396  		require.NoError(t, err)
   397  		require.Equal(t, pk, bytea)
   398  
   399  		bytea = []byte(nil)
   400  		err = Unmarshal(nullval, &bytea)
   401  		require.NoError(t, err)
   402  		require.Equal(t, []byte(nil), bytea)
   403  	})
   404  
   405  	t.Run("Unmarshal Time", func(it *testing.T) {
   406  		var dt time.Time
   407  		date := `2018-01-02T15:04:33Z`
   408  		b = []byte(`"` + date + `"`)
   409  
   410  		err = Unmarshal(b, &dt)
   411  		require.NoError(t, err)
   412  		require.Equal(t, date, dt.UTC().Format(time.RFC3339))
   413  
   414  		err = Unmarshal(nullval, &dt)
   415  		require.NoError(t, err)
   416  		require.Equal(t, `0001-01-01T00:00:00Z`, dt.UTC().Format(time.RFC3339))
   417  	})
   418  
   419  	t.Run("Unmarshal Array", func(it *testing.T) {
   420  		var (
   421  			nullArr   []string
   422  			initArr   []int
   423  			strArr    []string
   424  			intArr    []int
   425  			twoDArr   [][]int
   426  			threeDArr [][][]string
   427  		)
   428  
   429  		nullArr = []string{"xyz"}
   430  		err = Unmarshal(nullval, &nullArr)
   431  		require.NoError(t, err)
   432  		require.Equal(t, []string(nil), nullArr)
   433  
   434  		err = Unmarshal([]byte(`null`), &nullArr)
   435  		require.NoError(t, err)
   436  		require.Equal(t, []string(nil), nullArr)
   437  
   438  		err = Unmarshal([]byte("[]"), &initArr)
   439  		require.NoError(t, err)
   440  		require.NotNil(t, initArr)
   441  		require.Equal(t, make([]int, 0), initArr)
   442  
   443  		err = Unmarshal([]byte(`["a", "b", "c"]`), &strArr)
   444  		require.NoError(t, err)
   445  		require.ElementsMatch(t, []string{"a", "b", "c"}, strArr)
   446  
   447  		err = Unmarshal([]byte(`[2, 8, 32, 64, 128]`), &intArr)
   448  		require.NoError(t, err)
   449  		require.ElementsMatch(t, []int{2, 8, 32, 64, 128}, intArr)
   450  
   451  		err = Unmarshal([]byte(`[
   452  			[2, 8, 32, 64, 128],
   453  			[1, 3, 5, 7],
   454  			[0, 100, 1000, 10000, 100000]
   455  		]`), &twoDArr)
   456  		require.ElementsMatch(t, [][]int{
   457  			{2, 8, 32, 64, 128},
   458  			{1, 3, 5, 7},
   459  			{0, 100, 1000, 10000, 100000},
   460  		}, twoDArr)
   461  		require.NoError(t, err)
   462  
   463  		err = Unmarshal([]byte(`[
   464  			[
   465  				["a", "b", "c", "d", "e"],
   466  				["η”²", "δΉ™", "δΈ™", "丁"],
   467  				["πŸ˜„", "πŸ˜…", "πŸ˜†", "πŸ˜‰", "😊"]
   468  			],
   469  			[
   470  				["a", "b", "c", "d", "e"],
   471  				["f", "g", "h", "i", "j"]
   472  			],
   473  			[
   474  				["Java", "JavaScript", "TypeScript"],
   475  				["Rust", "GoLang"]
   476  			]
   477  		]`), &threeDArr)
   478  		require.NoError(t, err)
   479  		require.ElementsMatch(t, [][][]string{{
   480  			[]string{"a", "b", "c", "d", "e"},
   481  			[]string{"η”²", "δΉ™", "δΈ™", "丁"},
   482  			[]string{"πŸ˜„", "πŸ˜…", "πŸ˜†", "πŸ˜‰", "😊"},
   483  		}, {
   484  			[]string{"a", "b", "c", "d", "e"},
   485  			[]string{"f", "g", "h", "i", "j"},
   486  		}, {
   487  			[]string{"Java", "JavaScript", "TypeScript"},
   488  			[]string{"Rust", "GoLang"},
   489  		}}, threeDArr)
   490  
   491  		b := []byte(`[{"Name":   "John", 
   492  		"Email": "john@hotmail.com"   ,
   493  		"Age" : 20,
   494  		},  {"Name":   " πŸ˜ƒ πŸ˜„ πŸ˜… πŸ˜† πŸ˜‰ 😊 πŸ˜‹ 😎 😍", 
   495  		"Email": "test@hotmail.com"   ,
   496  		"Age" : 88,
   497  		"UUID": "daa68da0-8890-11ea-bc55-0242ac130003"
   498  		}]`)
   499  
   500  		users := []User{}
   501  		err = Unmarshal(b, &users)
   502  		require.NoError(t, err)
   503  		id := uuid.MustParse("daa68da0-8890-11ea-bc55-0242ac130003")
   504  		require.ElementsMatch(t, []User{
   505  			{Name: "John", Email: "john@hotmail.com", Age: 20},
   506  			{Name: " πŸ˜ƒ πŸ˜„ πŸ˜… πŸ˜† πŸ˜‰ 😊 πŸ˜‹ 😎 😍", Email: "test@hotmail.com", Age: 88, UUID: id},
   507  		}, users)
   508  
   509  		type recursiveNestedStruct struct {
   510  			Unicode   string
   511  			String    string
   512  			Boolean   bool
   513  			Integer   int
   514  			Level     uint
   515  			Recursive *recursiveNestedStruct
   516  			Float     float64
   517  			Time      time.Time
   518  			Nested    *struct {
   519  				Name     string
   520  				No       int
   521  				StrSlice []string
   522  			}
   523  		}
   524  
   525  		b = []byte(`
   526  		[{
   527  			"Unicode" : "δΈ­ε›½β˜…",
   528  			"String": "hello world",
   529  				"Level" : 1,
   530  			"Time": "2017-02-05T03:46:15Z",
   531  			"Recursive": {},
   532  			"Nested": {
   533  				"No" : 2,
   534  				"StrSlice": ["a", "b", "c"],
   535  			}
   536  		}]
   537  		`)
   538  
   539  		structs := []recursiveNestedStruct{}
   540  		err = Unmarshal(b, &structs)
   541  		require.NoError(t, err)
   542  
   543  		f := structs[0]
   544  		require.NotNil(t, f.Nested)
   545  		require.Equal(t, "δΈ­ε›½β˜…", f.Unicode)
   546  		require.Equal(t, uint(1), f.Level)
   547  		require.Equal(t, "hello world", f.String)
   548  		require.Equal(t, 2, f.Nested.No)
   549  		require.ElementsMatch(t, []string{"a", "b", "c"}, f.Nested.StrSlice)
   550  	})
   551  
   552  	t.Run("Unmarshal Map", func(it *testing.T) {
   553  		data := make(map[customKey]string)
   554  
   555  		err = Unmarshal([]byte(`{"test":"hello" ,  "test2": "world"}`), &data)
   556  		require.NoError(t, err)
   557  
   558  		k1 := customKey{value: "test"}
   559  		k2 := customKey{value: "test2"}
   560  
   561  		require.Contains(t, data, k1)
   562  		require.Contains(t, data, k2)
   563  
   564  		require.Equal(t, data[k1], "hello")
   565  		require.Equal(t, data[k2], "world")
   566  	})
   567  
   568  	t.Run("Unmarshal Struct", func(it *testing.T) {
   569  		{
   570  			// unmarshal with empty object {}
   571  			b = []byte(`   {   } `)
   572  			var a struct{}
   573  			err = Unmarshal(b, &a)
   574  			require.NoError(it, err)
   575  			require.Equal(t, struct{}{}, a)
   576  		}
   577  
   578  		{
   579  			b = []byte(`
   580  		{
   581  			"Str" :"hello world!!" ,
   582  			"UUID":     "4c03d1de-645b-40d2-9ed5-12bb537a602e",
   583  			"SymbolStr"   : "x1#$%^\t!\n\t\t@#$%^&*())))?\\<>.,/:\":;'{}[]-=+_~",
   584  			"EscapeStr"     :    "<html><div>hello world!</div></html>",
   585  			"StrSlice" : ["a", "b", "c", "d"],
   586  			"Users" : [
   587  				{"Name":"SianLoong",   "Age": 18}   ,
   588  			 { "Name":"Junkai"}],
   589  			"Nested": {
   590  				"NilKey": null,
   591  				"MultiNilPtrKey": null,
   592  				"MultiPtr": "testing \"multiple\" pointer",
   593  				"Security"   : {
   594  					"PrivateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDWFFJQkFBS0JnUUMrYUlTemtOdXFiZmdxWW9IYW1iS0dyaEF6UnV0dWYydWFzOUJIeXllUFJUdUk5ZVdwCnJHY3lRZlhPVlh2OGJBZVMxK2tIS0MvK1ZDTk9EbGZBTFlQWVVZa053eHVvRnFMbU1SR3E1MzMwSEVLSUpySDcKSUU5aUs0QUVZL3h5WjBTUEp5ZkNnQ2ZaeGtJTmpacWFoSS8rVWxrL1BmdWwyaEQ0ZTNUZVpGTm5HUUlEQVFBQgpBb0dBSHpOYlExMWlVV3dSdFVoTkJQZ1lnKzh6NG1NbG93YW9LRUo4eDdibmRaZWZxTks2WG5KTXVyU0tSZFJHCks5ZTc2ZmtOUzBudmkxcFlLcXM0LzltMWQ4Mk9XdmtDeXZvR3pmRXdyNGJ6bVBBZjdkczVkWElhb29wbWV4WWwKbFpsSmtuMDhWNFJmOWc4RFEyNFRsb3BpZ3RrSzY5UktRSzFHaHVyV1A4UjVxeTBDUVFEZ3dxcGVKZFF5RUdaYgpQUElJN2ZsSUVDRjlQNnNVc1ovNW40cEhNNmg2N0dOdGU1cEx4bDkzOXYybVhaN09aSUZHQU1rUmNDL1ZIK3c4Cm5oaytaNE9yQWtFQTJOK01oOWRpN1YreldaNUNIWXBWTHM5Qi9xOVl3YjFCNjN0UnZUbG9QSnFqTHc1NDUzZUUKbEs0ZnJSaVhXbEhLaUpLYlBOTU1ZUVkyTVRrcEQ2dDhTd0pCQUlkU2JRVFdQZFlPcmJITkZlUnVjeUlDSkVlbQpwN2lENFUrSDBOZGhzTlNoc3BOZVVkM0JpQVZRZmhOR1ZyRHBMalFaa1BXZzJBdTNkcUpnaGM1ZXdKVUNRQUVFCkV4RnoxZGZNMGZkQ2dZYkg1aHhCQmtzZUlTbFBMS2JndmdKSDZaQVhIVnFVRThicHpXb3c0cDhaOVdPTDdJbjEKUGRyc0ZpdkNMckRPVnIzbkRMOENRUURKSENwSEVFNTc0ckpzblJNYk5rR0F5dmZheW9MeElhVUF5WXovaGxrMgpzQ0wzb3BsdDNYM0tjYzV1MkRISVFsZTdGM1M4Wmp4REZMSVRrbnJ4QS9UVgotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ=="
   595  				},
   596  				"Test" :"hello world!!" ,
   597  				"Test2" :"hello world!!" ,
   598  				"Testxx" :"hello world!!" ,
   599  				"empty" :    {},
   600  				"nested"  : {
   601  					"deep0"  : 100,
   602  					"deep1" : {
   603  						"value" : 199303.00
   604  					},
   605  					"deep2": "YOLO"
   606  				}
   607  			},
   608  			"BigDecimal": 100.111,
   609  			"Integer": 6000,
   610  			"Bool": true
   611  		}`)
   612  
   613  			cp := make([]byte, len(b))
   614  			copy(cp, b)
   615  
   616  			var (
   617  				o           testStruct
   618  				nilKey      *types.Key
   619  				multiNilKey ******types.Key
   620  			)
   621  
   622  			o.Nested.Key = types.IDKey("XX", 100, nil)
   623  
   624  			err = Unmarshal(cp, &o)
   625  			require.NoError(t, err)
   626  
   627  			require.Nil(t, o.Nested.Key)
   628  			require.Equal(t, nilKey, o.Nested.Key)
   629  
   630  			require.Nil(t, o.Nested.NilKey)
   631  			require.Equal(t, nilKey, o.Nested.NilKey)
   632  
   633  			require.Nil(t, o.Nested.MultiNilPtrKey)
   634  			require.Equal(t, multiNilKey, o.Nested.MultiNilPtrKey)
   635  
   636  			// after unmarshal, the input should be the same (input shouldn't modified)
   637  			require.Equal(t, uuid.MustParse(`4c03d1de-645b-40d2-9ed5-12bb537a602e`), *****o.UUID)
   638  			require.Equal(t, `testing "multiple" pointer`, ***o.Nested.MultiPtr)
   639  			require.Equal(t, b, cp)
   640  			require.Equal(t, `hello world!!`, o.Str)
   641  			require.Equal(t, `x1#$%^	!
   642  		@#$%^&*())))?\<>.,/:":;'{}[]-=+_~`, o.SymbolStr)
   643  			require.Equal(t, pk, o.Nested.Security.PrivateKey)
   644  			require.Equal(t, true, o.Bool)
   645  			require.Equal(t, int(6000), o.Integer)
   646  			require.Equal(t, float64(100.111), o.BigDecimal)
   647  			require.ElementsMatch(t, []User{
   648  				{Name: "SianLoong", Age: 18},
   649  				{Name: "Junkai"},
   650  			}, o.Users)
   651  			require.ElementsMatch(t, []string{"a", "b", "c", "d"}, o.StrSlice)
   652  		}
   653  
   654  		{
   655  			var i User
   656  			i.Name = "testing"
   657  			i.Email = "sianloong90@gmail.com"
   658  			i.Age = 100
   659  			err = Unmarshal(nullval, &i)
   660  			require.NoError(t, err)
   661  			require.Equal(t, User{}, i)
   662  		}
   663  
   664  		{
   665  			u := new(User)
   666  			u.Name = "testing"
   667  			err = Unmarshal([]byte(`{"Name": "lol", "Email":"test@hotmail.com", "Age": 18}`), u)
   668  			require.NoError(t, err)
   669  			require.Equal(t, "lol", u.Name)
   670  			require.Equal(t, "test@hotmail.com", u.Email)
   671  			require.Equal(t, int(18), u.Age)
   672  		}
   673  	})
   674  
   675  	t.Run("Unmarshal Pointer Struct", func(it *testing.T) {
   676  		var ptr *ptrStruct
   677  		err = Unmarshal([]byte(`null`), &ptr)
   678  		require.NoError(t, err)
   679  
   680  		var nilptr *ptrStruct
   681  		require.Equal(t, nilptr, ptr)
   682  
   683  		initPtr := new(ptrStruct)
   684  		err = Unmarshal([]byte(`{
   685  			"PtrStr": "testing {}!@#$%^&*(\\",
   686  			"PtrBool": true,
   687  			"PtrInt": -100,
   688  			"PtrInt8": -88,
   689  			"PtrInt16": 8814,
   690  			"PtrInt64": -88818111321351212,
   691  			"PtrUint": 718222455,
   692  			"PtrUint8": 173,
   693  			"PtrUint16": 8814,
   694  			"PtrUint32": 2031273814,
   695  			"PtrUint64": 88818111321351212,
   696  			"PtrStrSlice" : ["a", "b", "c", "d"],
   697  			"PtrJSONRaw": {   "k1" : "value"  , "k2"  : "  value 1312$%^&*"},
   698  			"PtrJSONNumber" : 183939.778,
   699  			"PtrUintSlice" : [7, 88, 199, 200],
   700  			"PtrF32Slice" :  [10.88, 728.99, 722.00],
   701  			"PtrCurrencyUnit" : "MYR",
   702  			"PtrLanguageTag" : "en",
   703  			"PtrTime": "2008-01-26T00:00:58Z"
   704  		}`), initPtr)
   705  		require.NoError(t, err)
   706  
   707  		{
   708  			str := `testing {}!@#$%^&*(\`
   709  			require.Equal(t, &str, initPtr.PtrStr)
   710  			flag := true
   711  			require.Equal(t, &flag, initPtr.PtrBool)
   712  		}
   713  
   714  		{
   715  			i := int(-100)
   716  			require.Equal(t, &i, initPtr.PtrInt)
   717  			i8 := int8(-88)
   718  			require.Equal(t, &i8, initPtr.PtrInt8)
   719  			i16 := int16(8814)
   720  			require.Equal(t, &i16, initPtr.PtrInt16)
   721  			i64 := int64(-88818111321351212)
   722  			require.Equal(t, &i64, initPtr.PtrInt64)
   723  		}
   724  
   725  		{
   726  			ui := uint(718222455)
   727  			require.Equal(t, &ui, initPtr.PtrUint)
   728  			ui8 := uint8(173)
   729  			require.Equal(t, &ui8, initPtr.PtrUint8)
   730  			ui16 := uint16(8814)
   731  			require.Equal(t, &ui16, initPtr.PtrUint16)
   732  			ui32 := uint32(2031273814)
   733  			require.Equal(t, &ui32, initPtr.PtrUint32)
   734  			ui64 := uint64(88818111321351212)
   735  			require.Equal(t, &ui64, initPtr.PtrUint64)
   736  		}
   737  
   738  		{
   739  			var nilByte *[]byte
   740  			require.Equal(t, nilByte, initPtr.PtrByte)
   741  		}
   742  
   743  		{
   744  			raw := json.RawMessage(`{"k1":"value","k2":"  value 1312$%^&*"}`)
   745  			require.Equal(t, &raw, initPtr.PtrJSONRaw)
   746  		}
   747  
   748  		{
   749  			num := json.Number("183939.778")
   750  			require.Equal(t, &num, initPtr.PtrJSONNumber)
   751  			f64, _ := initPtr.PtrJSONNumber.Float64()
   752  			require.Equal(t, float64(183939.778), f64)
   753  			i64, _ := initPtr.PtrJSONNumber.Int64()
   754  			require.Equal(t, int64(0), i64)
   755  		}
   756  
   757  		{
   758  			slice := []string{"a", "b", "c", "d"}
   759  			require.Equal(t, &slice, initPtr.PtrStrSlice)
   760  		}
   761  
   762  		{
   763  			require.Nil(it, initPtr.PtrUUID)
   764  			require.Nil(it, initPtr.PtrIntSlice)
   765  		}
   766  
   767  		{
   768  			slice := []uint{7, 88, 199, 200}
   769  			require.Equal(t, &slice, initPtr.PtrUintSlice)
   770  		}
   771  
   772  		{
   773  			slice := []float32{10.88, 728.99, 722.00}
   774  			require.Equal(t, &slice, initPtr.PtrF32Slice)
   775  		}
   776  
   777  		{
   778  			lang := language.English
   779  			require.Equal(t, &lang, initPtr.PtrLanguageTag)
   780  		}
   781  
   782  		{
   783  			unit, _ := currency.ParseISO("MYR")
   784  			require.Equal(t, &unit, initPtr.PtrCurrencyUnit)
   785  		}
   786  
   787  		{
   788  			dt, _ := time.Parse(time.RFC3339, "2008-01-26T00:00:58Z")
   789  			require.Equal(t, &dt, initPtr.PtrTime)
   790  		}
   791  	})
   792  }
   793  
   794  func BenchmarkJSONUnmarshal(b *testing.B) {
   795  	data := []byte(`
   796  	{         
   797  		"Test" :"hello world!!" ,
   798  		"Test2"   : "x1#$%^&*xx",
   799  		"Test4": {
   800  			"Test" :"hello world!!" ,
   801  			"Test2" :"hello world!!" ,
   802  			"Testxx" :"hello world!!" , 
   803  			"empty" :    {},
   804  			"nested"  : {
   805  				"deep0"  : 100,
   806  				"deep1" : {
   807  					"value" : 199303.00
   808  				},
   809  				"deep2": "YOLO"
   810  			}
   811  		},
   812  		"Test0": 100.111,
   813  		"Test99": 6000,
   814  		"Bool": true
   815  	}   		
   816  	
   817  	`)
   818  	var (
   819  		o   testStruct
   820  		err error
   821  	)
   822  
   823  	for n := 0; n < b.N; n++ {
   824  		err = json.Unmarshal(data, &o)
   825  		require.NoError(b, err)
   826  	}
   827  }
   828  
   829  func BenchmarkJSONBUnmarshal(b *testing.B) {
   830  	// data := []byte(`
   831  	// {
   832  	// 	"Test" :"hello world!!" ,
   833  	// 	"Test2"   : "x1#$%^&*xx",
   834  	// 	"Test4": {
   835  	// 		"Test" :"hello world!!" ,
   836  	// 		"Test2" :"hello world!!" ,
   837  	// 		"Testxx" :"hello world!!" ,
   838  	// 		"empty" :    {},
   839  	// 		"nested"  : {
   840  	// 			"deep0"  : 100,
   841  	// 			"deep1" : {
   842  	// 				"value" : 199303.00
   843  	// 			},
   844  	// 			"deep2": "YOLO"
   845  	// 		}
   846  	// 	},
   847  	// 	"Test0": 100.111,
   848  	// 	"Test99": 6000,
   849  	// 	"Bool": true
   850  	// }
   851  
   852  	// `)
   853  	// var (
   854  	// 	o   testStruct
   855  	// 	err error
   856  	// )
   857  	// for n := 0; n < b.N; n++ {
   858  	// 	err = Unmarshal(data, &o)
   859  	// 	require.NoError(b, err)
   860  	// }
   861  }