...

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

Documentation: github.com/stretchr/objx

     1  package objx
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"errors"
     7  	"io/ioutil"
     8  	"net/url"
     9  	"strings"
    10  )
    11  
    12  // MSIConvertable is an interface that defines methods for converting your
    13  // custom types to a map[string]interface{} representation.
    14  type MSIConvertable interface {
    15  	// MSI gets a map[string]interface{} (msi) representing the
    16  	// object.
    17  	MSI() map[string]interface{}
    18  }
    19  
    20  // Map provides extended functionality for working with
    21  // untyped data, in particular map[string]interface (msi).
    22  type Map map[string]interface{}
    23  
    24  // Value returns the internal value instance
    25  func (m Map) Value() *Value {
    26  	return &Value{data: m}
    27  }
    28  
    29  // Nil represents a nil Map.
    30  var Nil = New(nil)
    31  
    32  // New creates a new Map containing the map[string]interface{} in the data argument.
    33  // If the data argument is not a map[string]interface, New attempts to call the
    34  // MSI() method on the MSIConvertable interface to create one.
    35  func New(data interface{}) Map {
    36  	if _, ok := data.(map[string]interface{}); !ok {
    37  		if converter, ok := data.(MSIConvertable); ok {
    38  			data = converter.MSI()
    39  		} else {
    40  			return nil
    41  		}
    42  	}
    43  	return Map(data.(map[string]interface{}))
    44  }
    45  
    46  // MSI creates a map[string]interface{} and puts it inside a new Map.
    47  //
    48  // The arguments follow a key, value pattern.
    49  //
    50  // Returns nil if any key argument is non-string or if there are an odd number of arguments.
    51  //
    52  // # Example
    53  //
    54  // To easily create Maps:
    55  //
    56  //	m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true))
    57  //
    58  //	// creates an Map equivalent to
    59  //	m := objx.Map{"name": "Mat", "age": 29, "subobj": objx.Map{"active": true}}
    60  func MSI(keyAndValuePairs ...interface{}) Map {
    61  	newMap := Map{}
    62  	keyAndValuePairsLen := len(keyAndValuePairs)
    63  	if keyAndValuePairsLen%2 != 0 {
    64  		return nil
    65  	}
    66  	for i := 0; i < keyAndValuePairsLen; i = i + 2 {
    67  		key := keyAndValuePairs[i]
    68  		value := keyAndValuePairs[i+1]
    69  
    70  		// make sure the key is a string
    71  		keyString, keyStringOK := key.(string)
    72  		if !keyStringOK {
    73  			return nil
    74  		}
    75  		newMap[keyString] = value
    76  	}
    77  	return newMap
    78  }
    79  
    80  // ****** Conversion Constructors
    81  
    82  // MustFromJSON creates a new Map containing the data specified in the
    83  // jsonString.
    84  //
    85  // Panics if the JSON is invalid.
    86  func MustFromJSON(jsonString string) Map {
    87  	o, err := FromJSON(jsonString)
    88  	if err != nil {
    89  		panic("objx: MustFromJSON failed with error: " + err.Error())
    90  	}
    91  	return o
    92  }
    93  
    94  // MustFromJSONSlice creates a new slice of Map containing the data specified in the
    95  // jsonString. Works with jsons with a top level array
    96  //
    97  // Panics if the JSON is invalid.
    98  func MustFromJSONSlice(jsonString string) []Map {
    99  	slice, err := FromJSONSlice(jsonString)
   100  	if err != nil {
   101  		panic("objx: MustFromJSONSlice failed with error: " + err.Error())
   102  	}
   103  	return slice
   104  }
   105  
   106  // FromJSON creates a new Map containing the data specified in the
   107  // jsonString.
   108  //
   109  // Returns an error if the JSON is invalid.
   110  func FromJSON(jsonString string) (Map, error) {
   111  	var m Map
   112  	err := json.Unmarshal([]byte(jsonString), &m)
   113  	if err != nil {
   114  		return Nil, err
   115  	}
   116  	return m, nil
   117  }
   118  
   119  // FromJSONSlice creates a new slice of Map containing the data specified in the
   120  // jsonString. Works with jsons with a top level array
   121  //
   122  // Returns an error if the JSON is invalid.
   123  func FromJSONSlice(jsonString string) ([]Map, error) {
   124  	var slice []Map
   125  	err := json.Unmarshal([]byte(jsonString), &slice)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  	return slice, nil
   130  }
   131  
   132  // FromBase64 creates a new Obj containing the data specified
   133  // in the Base64 string.
   134  //
   135  // The string is an encoded JSON string returned by Base64
   136  func FromBase64(base64String string) (Map, error) {
   137  	decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String))
   138  	decoded, err := ioutil.ReadAll(decoder)
   139  	if err != nil {
   140  		return nil, err
   141  	}
   142  	return FromJSON(string(decoded))
   143  }
   144  
   145  // MustFromBase64 creates a new Obj containing the data specified
   146  // in the Base64 string and panics if there is an error.
   147  //
   148  // The string is an encoded JSON string returned by Base64
   149  func MustFromBase64(base64String string) Map {
   150  	result, err := FromBase64(base64String)
   151  	if err != nil {
   152  		panic("objx: MustFromBase64 failed with error: " + err.Error())
   153  	}
   154  	return result
   155  }
   156  
   157  // FromSignedBase64 creates a new Obj containing the data specified
   158  // in the Base64 string.
   159  //
   160  // The string is an encoded JSON string returned by SignedBase64
   161  func FromSignedBase64(base64String, key string) (Map, error) {
   162  	parts := strings.Split(base64String, SignatureSeparator)
   163  	if len(parts) != 2 {
   164  		return nil, errors.New("objx: Signed base64 string is malformed")
   165  	}
   166  
   167  	sig := HashWithKey(parts[0], key)
   168  	if parts[1] != sig {
   169  		return nil, errors.New("objx: Signature for base64 data does not match")
   170  	}
   171  	return FromBase64(parts[0])
   172  }
   173  
   174  // MustFromSignedBase64 creates a new Obj containing the data specified
   175  // in the Base64 string and panics if there is an error.
   176  //
   177  // The string is an encoded JSON string returned by Base64
   178  func MustFromSignedBase64(base64String, key string) Map {
   179  	result, err := FromSignedBase64(base64String, key)
   180  	if err != nil {
   181  		panic("objx: MustFromSignedBase64 failed with error: " + err.Error())
   182  	}
   183  	return result
   184  }
   185  
   186  // FromURLQuery generates a new Obj by parsing the specified
   187  // query.
   188  //
   189  // For queries with multiple values, the first value is selected.
   190  func FromURLQuery(query string) (Map, error) {
   191  	vals, err := url.ParseQuery(query)
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  	m := Map{}
   196  	for k, vals := range vals {
   197  		m[k] = vals[0]
   198  	}
   199  	return m, nil
   200  }
   201  
   202  // MustFromURLQuery generates a new Obj by parsing the specified
   203  // query.
   204  //
   205  // For queries with multiple values, the first value is selected.
   206  //
   207  // Panics if it encounters an error
   208  func MustFromURLQuery(query string) Map {
   209  	o, err := FromURLQuery(query)
   210  	if err != nil {
   211  		panic("objx: MustFromURLQuery failed with error: " + err.Error())
   212  	}
   213  	return o
   214  }
   215  

View as plain text