Skip to content

Instantly share code, notes, and snippets.

@aimuz
Created August 28, 2020 12:58
Show Gist options
  • Save aimuz/cd930774ca1de00e2dc77315ccd5e3f9 to your computer and use it in GitHub Desktop.
Save aimuz/cd930774ca1de00e2dc77315ccd5e3f9 to your computer and use it in GitHub Desktop.
Generate the corresponding pre signature string according to the object
package sign
import (
"reflect"
"sort"
"strconv"
"strings"
)
// GeneratePreSign from objects generates a pre-signed message
func GeneratePreSign(value interface{}) string {
valueOf := reflect.ValueOf(value)
return generatePreSign(valueOf)
}
func generatePreSign(valueOf reflect.Value) string {
valueOf = originalValue(valueOf)
kind := valueOf.Kind()
var (
kvs []string
childOf reflect.Value
)
switch kind {
case reflect.String:
str := valueOf.String()
str = strings.Replace(str, " ", "", -1)
kvs = make([]string, len(str))
for i, s := range str {
kvs[i] = strconv.Itoa(i) + "=" + string(s)
}
case reflect.Map:
keys := valueOf.MapKeys()
kvs = make([]string, len(keys))
for i, key := range keys {
childOf = originalValue(valueOf.MapIndex(key))
kvs[i] = key.String() + "=" + generateObjectString(childOf)
}
case reflect.Struct:
typeOf := valueOf.Type()
var (
childField reflect.StructField
tag string
)
num := typeOf.NumField()
kvs = make([]string, num)
for i := 0; i < num; i++ {
childField = typeOf.Field(i)
childOf = originalValue(valueOf.Field(i))
tag = strings.Split(childField.Tag.Get("json"), ",")[0]
if tag == "-" {
continue
}
if len(tag) > 0 {
kvs[i] += tag
} else {
kvs[i] += childField.Name
}
kvs[i] += "=" + generateObjectString(childOf)
}
case reflect.Array, reflect.Slice:
kvs = make([]string, 0, valueOf.Len())
for i := 0; i < valueOf.Len(); i++ {
childOf = valueOf.Index(i)
kvs[i] = strconv.Itoa(i) + "=" + generateObjectString(childOf)
}
}
sort.Strings(kvs)
return strings.Join(kvs, "&")
}
func generateObjectString(valueOf reflect.Value) string {
kind := valueOf.Kind()
if isObject(kind) {
return "{" + generatePreSign(valueOf) + "}"
} else if isArray(kind) {
var result string
var childOf reflect.Value
valueOfLen := valueOf.Len()
for i := 0; i < valueOfLen; i++ {
childOf = originalValue(valueOf.Index(i))
kind = childOf.Kind()
if isObject(kind) || isArray(kind) {
result += "{" + generatePreSign(childOf) + "}"
} else {
result += toStrings(childOf)
}
if i < valueOfLen-1 {
result += ","
}
}
return result
}
return toStrings(valueOf)
}
func toStrings(valueOf reflect.Value) string {
switch valueOf.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(valueOf.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.FormatUint(valueOf.Uint(), 10)
case reflect.Float32, reflect.Float64:
return strconv.FormatFloat(valueOf.Float(), 'f', -1, 64)
case reflect.Bool:
return strconv.FormatBool(valueOf.Bool())
case reflect.String:
return valueOf.String()
}
return ""
}
func isObject(kind reflect.Kind) bool {
return kind == reflect.Map || kind == reflect.Struct
}
func isArray(kind reflect.Kind) bool {
return kind == reflect.Array || kind == reflect.Slice
}
func originalValue(value reflect.Value) reflect.Value {
for {
switch value.Kind() {
case reflect.Ptr:
value = value.Elem()
case reflect.Interface:
value = reflect.ValueOf(value.Interface())
default:
return value
}
}
}
@aimuz
Copy link
Author

aimuz commented Aug 28, 2020

input

output := GeneratePreSign(map[string]interface{}{
		"username": "username",
		"info": map[string]interface{}{
			"head": "head",
			"city": map[string]interface{}{
				"address": "japan",
			},
			"phone": []string{
				"123456789",
				"234567890",
			},
		},
		"struct": struct {
			Name string `json:"name"`
		}{
			Name: "jack",
		},
		"isFoozed": true,
	})

output

info={city={address=japan}&head=head&phone=123456789,234567890}&isFoozed=true&struct={name=jack}&username=username

@aimuz
Copy link
Author

aimuz commented Aug 28, 2020

A general method of generating pre string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment