github.com/bytedance/go-tagexpr/v2@v2.9.8/binding/gjson/gjson_test.go (about)

     1  package gjson
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"math/rand"
     7  	"reflect"
     8  	"sync"
     9  	"testing"
    10  
    11  	"github.com/andeya/ameda"
    12  	"github.com/stretchr/testify/assert"
    13  
    14  	"github.com/bytedance/go-tagexpr/v2/binding/gjson/internal/rt"
    15  )
    16  
    17  func TestMap(t *testing.T) {
    18  	type X struct {
    19  		M1 map[string]interface{}
    20  		M2 map[string]struct {
    21  			A string
    22  			B int
    23  		}
    24  		M3 map[string]*struct {
    25  			A string
    26  			B int
    27  		}
    28  	}
    29  	x := X{
    30  		M1: map[string]interface{}{"i": float64(9), "j": "*"},
    31  		M2: map[string]struct {
    32  			A string
    33  			B int
    34  		}{"k2": {"a2", 12}},
    35  		M3: map[string]*struct {
    36  			A string
    37  			B int
    38  		}{"k3": {"a2", 13}},
    39  	}
    40  	data, _ := json.MarshalIndent(x, "", "  ")
    41  	t.Log(string(data))
    42  
    43  	var x2 X
    44  
    45  	err := Unmarshal(data, &x2)
    46  	assert.NoError(t, err)
    47  	assert.Equal(t, x, x2)
    48  
    49  	data = []byte(`{
    50            "M1": {
    51              "i": 9,
    52              "j": "*"
    53            },
    54            "M2": {
    55              "k2": {
    56                "A": "a2",
    57                "B": 12
    58              }
    59            },
    60            "M3": {
    61              "k3": {
    62                "A": "a2",
    63                "B": "13"
    64              }
    65            }
    66          }`)
    67  
    68  	var x3 *X
    69  	err = Unmarshal(data, &x3)
    70  	assert.NoError(t, err)
    71  	assert.Equal(t, x, *x3)
    72  }
    73  
    74  func TestStruct(t *testing.T) {
    75  	type a struct {
    76  		V int `json:"v"`
    77  	}
    78  	type B struct {
    79  		a
    80  		A2 **a
    81  	}
    82  	type C struct {
    83  		*B `json:"b"`
    84  	}
    85  	type D struct {
    86  		*C `json:","`
    87  		C2 *int
    88  	}
    89  	type E struct {
    90  		D
    91  		K int `json:"k"`
    92  		int
    93  	}
    94  	data := []byte(`{
    95  "k":1,
    96  "C2":null,
    97  "b":{"v":2,"A2":{"v":3}}
    98  }`)
    99  	std := &E{}
   100  	err := json.Unmarshal(data, std)
   101  	if assert.NoError(t, err) {
   102  		assert.Equal(t, 1, std.K)
   103  		assert.Equal(t, 2, std.V)
   104  		assert.Equal(t, 3, (*std.A2).V)
   105  	}
   106  	g := &E{}
   107  	err = Unmarshal(data, g)
   108  	assert.NoError(t, err)
   109  	assert.Equal(t, std, g)
   110  
   111  	type X struct {
   112  		*X
   113  		Y int
   114  	}
   115  	data2 := []byte(`{"X":{"Y":2}}`)
   116  	std2 := &X{}
   117  	err = json.Unmarshal(data2, std2)
   118  	if assert.NoError(t, err) {
   119  		t.Logf("%#v", std2)
   120  	}
   121  	g2 := &X{}
   122  	err = Unmarshal(data2, g2)
   123  	assert.NoError(t, err)
   124  	assert.Equal(t, std2, g2)
   125  }
   126  
   127  func TestAliasBUG1(t *testing.T) {
   128  	type DeviceUUID string
   129  	type DeviceUUIDMap map[DeviceUUID]string
   130  	type AttachedMobiles struct {
   131  		AttachedAndroid DeviceUUIDMap `json:"android,omitempty"`
   132  		AttachedIOS     DeviceUUIDMap `json:"ios,omitempty"`
   133  	}
   134  	b, err := json.MarshalIndent(ameda.InitSampleValue(reflect.TypeOf(AttachedMobiles{}), 10).Interface(), "", "  ")
   135  	assert.NoError(t, err)
   136  	var r AttachedMobiles
   137  	err = Unmarshal(b, &r)
   138  	assert.NoError(t, err)
   139  	// b, err = json.Marshal(map[float32]int{
   140  	// 	1.0: 4,
   141  	// })
   142  	// assert.NoError(t, err)
   143  	// t.Log(string(b))
   144  }
   145  
   146  func TestBingSliceWithObject(t *testing.T) {
   147  	type F struct {
   148  		UID int64
   149  	}
   150  	type foo struct {
   151  		F1 []F `json:"f1"`
   152  		F2 []F `json:"f2"`
   153  	}
   154  	str := `{"f1":{"UID":1},"f2":[{"UID":"2233"}]}`
   155  
   156  	obj := foo{}
   157  	err := Unmarshal([]byte(str), &obj)
   158  
   159  	assert.NoError(t, err)
   160  	assert.Len(t, obj.F1, 0)
   161  }
   162  func BenchmarkGetFiledInfo(b *testing.B) {
   163  	var types []reflect.Type
   164  	const count = 2000
   165  	for i := 0; i < count; i++ {
   166  		xtype := genStruct(i)
   167  
   168  		getFiledInfo(xtype)
   169  
   170  		types = append(types, xtype)
   171  	}
   172  	b.ResetTimer()
   173  	b.RunParallel(func(pb *testing.PB) {
   174  		var i int64
   175  		for pb.Next() {
   176  			getFiledInfo(types[i%count])
   177  			i++
   178  		}
   179  	})
   180  }
   181  func BenchmarkGetFieldInfoByMap(b *testing.B) {
   182  	var types []reflect.Type
   183  	const count = 2000
   184  	for i := 0; i < count; i++ {
   185  		xtype := genStruct(i)
   186  
   187  		getFiledInfoWithMap(xtype)
   188  
   189  		types = append(types, xtype)
   190  	}
   191  	b.ResetTimer()
   192  	b.RunParallel(func(pb *testing.PB) {
   193  		var i int64
   194  		for pb.Next() {
   195  			getFiledInfoWithMap(types[i%count])
   196  			i++
   197  		}
   198  	})
   199  }
   200  
   201  func genStruct(n int) reflect.Type {
   202  	numOfFields := rand.Intn(50) + 1
   203  	field := make([]reflect.StructField, 0, numOfFields)
   204  	for i := 0; i < numOfFields; i++ {
   205  		field = append(field, reflect.StructField{
   206  			Name:    fmt.Sprintf("F%d_%d", n, i),
   207  			PkgPath: "",
   208  			Type: reflect.TypeOf(struct {
   209  				A int
   210  				B map[int]interface{}
   211  			}{}),
   212  		})
   213  	}
   214  	ot := reflect.StructOf(field)
   215  	return ot
   216  }
   217  
   218  var fieldsmu sync.RWMutex
   219  var fields = make(map[uintptr]map[string][]int)
   220  
   221  func getFiledInfoWithMap(t reflect.Type) map[string][]int {
   222  
   223  	runtimeTypeID := ameda.RuntimeTypeID(t)
   224  	fieldsmu.RLock()
   225  	sf := fields[runtimeTypeID]
   226  	fieldsmu.RUnlock()
   227  	if sf == nil {
   228  		fieldsmu.Lock()
   229  		defer fieldsmu.Unlock()
   230  
   231  		d := rt.UnpackType(t)
   232  		sf1, _ := computeTypeInfo(d)
   233  		sf = sf1.(map[string][]int)
   234  		fields[runtimeTypeID] = sf
   235  
   236  	}
   237  	return sf
   238  }
   239  
   240  // MarshalJSON to output non base64 encoded []byte
   241  func (j ByteSlice) MarshalJSON() ([]byte, error) {
   242  	if len(j) == 0 {
   243  		return []byte("null"), nil
   244  	}
   245  
   246  	return json.RawMessage(j).MarshalJSON()
   247  }
   248  
   249  // UnmarshalJSON to deserialize []byte
   250  func (j *ByteSlice) UnmarshalJSON(b []byte) error {
   251  	result := json.RawMessage{}
   252  	err := result.UnmarshalJSON(b)
   253  	*j = ByteSlice(result)
   254  	return err
   255  }
   256  
   257  type ByteSlice []byte
   258  
   259  func TestCustomizedGjsonUnmarshal(t *testing.T) {
   260  	str := `{"h1":{"h2":1}}`
   261  	type F struct {
   262  		H ByteSlice `json:"h1"`
   263  	}
   264  
   265  	obj := F{}
   266  	err := Unmarshal([]byte(str), &obj)
   267  
   268  	assert.NoError(t, err)
   269  	assert.Equal(t, "{\"h2\":1}", string(obj.H))
   270  
   271  	obj2 := F{}
   272  	err = json.Unmarshal([]byte(str), &obj2)
   273  	assert.NoError(t, err)
   274  	assert.Equal(t, "{\"h2\":1}", string(obj2.H))
   275  
   276  	assert.Equal(t, obj.H, obj2.H)
   277  }