github.com/gedevops/x@v1.0.3/jsonx/get.go (about)

     1  package jsonx
     2  
     3  import (
     4  	"reflect"
     5  	"strings"
     6  
     7  	"github.com/stretchr/testify/require"
     8  	"github.com/tidwall/gjson"
     9  )
    10  
    11  func jsonKey(f reflect.StructField) *string {
    12  	if jsonTag := f.Tag.Get("json"); jsonTag != "" {
    13  		if jsonTag == "-" {
    14  			return nil
    15  		}
    16  		return &strings.Split(jsonTag, ",")[0]
    17  	} else if f.Anonymous {
    18  		return nil
    19  	} else if f.IsExported() {
    20  		return &f.Name
    21  	}
    22  	return nil
    23  }
    24  
    25  // AllValidJSONKeys returns all JSON keys from the struct or *struct type.
    26  // It does not return keys from nested slices, but embedded/nested structs.
    27  func AllValidJSONKeys(s interface{}) (keys []string) {
    28  	t := reflect.TypeOf(s)
    29  	v := reflect.ValueOf(s)
    30  	if t.Kind() == reflect.Ptr {
    31  		t = t.Elem()
    32  		v = v.Elem()
    33  	}
    34  	for i := 0; i < t.NumField(); i++ {
    35  		f := t.Field(i)
    36  		jKey := jsonKey(f)
    37  		if k := f.Type.Kind(); k == reflect.Struct || k == reflect.Ptr {
    38  			subKeys := AllValidJSONKeys(v.Field(i).Interface())
    39  			for _, subKey := range subKeys {
    40  				if jKey != nil {
    41  					keys = append(keys, *jKey+"."+subKey)
    42  				} else {
    43  					keys = append(keys, subKey)
    44  				}
    45  			}
    46  		} else if jKey != nil {
    47  			keys = append(keys, *jKey)
    48  		}
    49  	}
    50  	return keys
    51  }
    52  
    53  // ParseEnsureKeys returns a result that has the GetRequireValidKey function.
    54  func ParseEnsureKeys(original interface{}, raw []byte) *Result {
    55  	return &Result{
    56  		keys:   AllValidJSONKeys(original),
    57  		result: gjson.ParseBytes(raw),
    58  	}
    59  }
    60  
    61  type Result struct {
    62  	result gjson.Result
    63  	keys   []string
    64  }
    65  
    66  // GetRequireValidKey ensures that the key is valid before returning the result.
    67  func (r *Result) GetRequireValidKey(t require.TestingT, key string) gjson.Result {
    68  	require.Contains(t, r.keys, key)
    69  	return r.result.Get(key)
    70  }
    71  
    72  func GetRequireValidKey(t require.TestingT, original interface{}, raw []byte, key string) gjson.Result {
    73  	return ParseEnsureKeys(original, raw).GetRequireValidKey(t, key)
    74  }