...

Source file src/github.com/stretchr/objx/conversions.go

Documentation: github.com/stretchr/objx

     1  package objx
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"net/url"
    10  	"strconv"
    11  )
    12  
    13  // SignatureSeparator is the character that is used to
    14  // separate the Base64 string from the security signature.
    15  const SignatureSeparator = "_"
    16  
    17  // URLValuesSliceKeySuffix is the character that is used to
    18  // specify a suffix for slices parsed by URLValues.
    19  // If the suffix is set to "[i]", then the index of the slice
    20  // is used in place of i
    21  // Ex: Suffix "[]" would have the form a[]=b&a[]=c
    22  // OR Suffix "[i]" would have the form a[0]=b&a[1]=c
    23  // OR Suffix "" would have the form a=b&a=c
    24  var urlValuesSliceKeySuffix = "[]"
    25  
    26  const (
    27  	URLValuesSliceKeySuffixEmpty = ""
    28  	URLValuesSliceKeySuffixArray = "[]"
    29  	URLValuesSliceKeySuffixIndex = "[i]"
    30  )
    31  
    32  // SetURLValuesSliceKeySuffix sets the character that is used to
    33  // specify a suffix for slices parsed by URLValues.
    34  // If the suffix is set to "[i]", then the index of the slice
    35  // is used in place of i
    36  // Ex: Suffix "[]" would have the form a[]=b&a[]=c
    37  // OR Suffix "[i]" would have the form a[0]=b&a[1]=c
    38  // OR Suffix "" would have the form a=b&a=c
    39  func SetURLValuesSliceKeySuffix(s string) error {
    40  	if s == URLValuesSliceKeySuffixEmpty || s == URLValuesSliceKeySuffixArray || s == URLValuesSliceKeySuffixIndex {
    41  		urlValuesSliceKeySuffix = s
    42  		return nil
    43  	}
    44  
    45  	return errors.New("objx: Invalid URLValuesSliceKeySuffix provided.")
    46  }
    47  
    48  // JSON converts the contained object to a JSON string
    49  // representation
    50  func (m Map) JSON() (string, error) {
    51  	for k, v := range m {
    52  		m[k] = cleanUp(v)
    53  	}
    54  
    55  	result, err := json.Marshal(m)
    56  	if err != nil {
    57  		err = errors.New("objx: JSON encode failed with: " + err.Error())
    58  	}
    59  	return string(result), err
    60  }
    61  
    62  func cleanUpInterfaceArray(in []interface{}) []interface{} {
    63  	result := make([]interface{}, len(in))
    64  	for i, v := range in {
    65  		result[i] = cleanUp(v)
    66  	}
    67  	return result
    68  }
    69  
    70  func cleanUpInterfaceMap(in map[interface{}]interface{}) Map {
    71  	result := Map{}
    72  	for k, v := range in {
    73  		result[fmt.Sprintf("%v", k)] = cleanUp(v)
    74  	}
    75  	return result
    76  }
    77  
    78  func cleanUpStringMap(in map[string]interface{}) Map {
    79  	result := Map{}
    80  	for k, v := range in {
    81  		result[k] = cleanUp(v)
    82  	}
    83  	return result
    84  }
    85  
    86  func cleanUpMSIArray(in []map[string]interface{}) []Map {
    87  	result := make([]Map, len(in))
    88  	for i, v := range in {
    89  		result[i] = cleanUpStringMap(v)
    90  	}
    91  	return result
    92  }
    93  
    94  func cleanUpMapArray(in []Map) []Map {
    95  	result := make([]Map, len(in))
    96  	for i, v := range in {
    97  		result[i] = cleanUpStringMap(v)
    98  	}
    99  	return result
   100  }
   101  
   102  func cleanUp(v interface{}) interface{} {
   103  	switch v := v.(type) {
   104  	case []interface{}:
   105  		return cleanUpInterfaceArray(v)
   106  	case []map[string]interface{}:
   107  		return cleanUpMSIArray(v)
   108  	case map[interface{}]interface{}:
   109  		return cleanUpInterfaceMap(v)
   110  	case Map:
   111  		return cleanUpStringMap(v)
   112  	case []Map:
   113  		return cleanUpMapArray(v)
   114  	default:
   115  		return v
   116  	}
   117  }
   118  
   119  // MustJSON converts the contained object to a JSON string
   120  // representation and panics if there is an error
   121  func (m Map) MustJSON() string {
   122  	result, err := m.JSON()
   123  	if err != nil {
   124  		panic(err.Error())
   125  	}
   126  	return result
   127  }
   128  
   129  // Base64 converts the contained object to a Base64 string
   130  // representation of the JSON string representation
   131  func (m Map) Base64() (string, error) {
   132  	var buf bytes.Buffer
   133  
   134  	jsonData, err := m.JSON()
   135  	if err != nil {
   136  		return "", err
   137  	}
   138  
   139  	encoder := base64.NewEncoder(base64.StdEncoding, &buf)
   140  	_, _ = encoder.Write([]byte(jsonData))
   141  	_ = encoder.Close()
   142  
   143  	return buf.String(), nil
   144  }
   145  
   146  // MustBase64 converts the contained object to a Base64 string
   147  // representation of the JSON string representation and panics
   148  // if there is an error
   149  func (m Map) MustBase64() string {
   150  	result, err := m.Base64()
   151  	if err != nil {
   152  		panic(err.Error())
   153  	}
   154  	return result
   155  }
   156  
   157  // SignedBase64 converts the contained object to a Base64 string
   158  // representation of the JSON string representation and signs it
   159  // using the provided key.
   160  func (m Map) SignedBase64(key string) (string, error) {
   161  	base64, err := m.Base64()
   162  	if err != nil {
   163  		return "", err
   164  	}
   165  
   166  	sig := HashWithKey(base64, key)
   167  	return base64 + SignatureSeparator + sig, nil
   168  }
   169  
   170  // MustSignedBase64 converts the contained object to a Base64 string
   171  // representation of the JSON string representation and signs it
   172  // using the provided key and panics if there is an error
   173  func (m Map) MustSignedBase64(key string) string {
   174  	result, err := m.SignedBase64(key)
   175  	if err != nil {
   176  		panic(err.Error())
   177  	}
   178  	return result
   179  }
   180  
   181  /*
   182  	URL Query
   183  	------------------------------------------------
   184  */
   185  
   186  // URLValues creates a url.Values object from an Obj. This
   187  // function requires that the wrapped object be a map[string]interface{}
   188  func (m Map) URLValues() url.Values {
   189  	vals := make(url.Values)
   190  
   191  	m.parseURLValues(m, vals, "")
   192  
   193  	return vals
   194  }
   195  
   196  func (m Map) parseURLValues(queryMap Map, vals url.Values, key string) {
   197  	useSliceIndex := false
   198  	if urlValuesSliceKeySuffix == "[i]" {
   199  		useSliceIndex = true
   200  	}
   201  
   202  	for k, v := range queryMap {
   203  		val := &Value{data: v}
   204  		switch {
   205  		case val.IsObjxMap():
   206  			if key == "" {
   207  				m.parseURLValues(val.ObjxMap(), vals, k)
   208  			} else {
   209  				m.parseURLValues(val.ObjxMap(), vals, key+"["+k+"]")
   210  			}
   211  		case val.IsObjxMapSlice():
   212  			sliceKey := k
   213  			if key != "" {
   214  				sliceKey = key + "[" + k + "]"
   215  			}
   216  
   217  			if useSliceIndex {
   218  				for i, sv := range val.MustObjxMapSlice() {
   219  					sk := sliceKey + "[" + strconv.FormatInt(int64(i), 10) + "]"
   220  					m.parseURLValues(sv, vals, sk)
   221  				}
   222  			} else {
   223  				sliceKey = sliceKey + urlValuesSliceKeySuffix
   224  				for _, sv := range val.MustObjxMapSlice() {
   225  					m.parseURLValues(sv, vals, sliceKey)
   226  				}
   227  			}
   228  		case val.IsMSISlice():
   229  			sliceKey := k
   230  			if key != "" {
   231  				sliceKey = key + "[" + k + "]"
   232  			}
   233  
   234  			if useSliceIndex {
   235  				for i, sv := range val.MustMSISlice() {
   236  					sk := sliceKey + "[" + strconv.FormatInt(int64(i), 10) + "]"
   237  					m.parseURLValues(New(sv), vals, sk)
   238  				}
   239  			} else {
   240  				sliceKey = sliceKey + urlValuesSliceKeySuffix
   241  				for _, sv := range val.MustMSISlice() {
   242  					m.parseURLValues(New(sv), vals, sliceKey)
   243  				}
   244  			}
   245  		case val.IsStrSlice(), val.IsBoolSlice(),
   246  			val.IsFloat32Slice(), val.IsFloat64Slice(),
   247  			val.IsIntSlice(), val.IsInt8Slice(), val.IsInt16Slice(), val.IsInt32Slice(), val.IsInt64Slice(),
   248  			val.IsUintSlice(), val.IsUint8Slice(), val.IsUint16Slice(), val.IsUint32Slice(), val.IsUint64Slice():
   249  
   250  			sliceKey := k
   251  			if key != "" {
   252  				sliceKey = key + "[" + k + "]"
   253  			}
   254  
   255  			if useSliceIndex {
   256  				for i, sv := range val.StringSlice() {
   257  					sk := sliceKey + "[" + strconv.FormatInt(int64(i), 10) + "]"
   258  					vals.Set(sk, sv)
   259  				}
   260  			} else {
   261  				sliceKey = sliceKey + urlValuesSliceKeySuffix
   262  				vals[sliceKey] = val.StringSlice()
   263  			}
   264  
   265  		default:
   266  			if key == "" {
   267  				vals.Set(k, val.String())
   268  			} else {
   269  				vals.Set(key+"["+k+"]", val.String())
   270  			}
   271  		}
   272  	}
   273  }
   274  
   275  // URLQuery gets an encoded URL query representing the given
   276  // Obj. This function requires that the wrapped object be a
   277  // map[string]interface{}
   278  func (m Map) URLQuery() (string, error) {
   279  	return m.URLValues().Encode(), nil
   280  }
   281  

View as plain text