Documentation ¶
Overview ¶
Package ordered provided a type OrderedMap for use in JSON handling although JSON spec says the keys order of an object should not matter but sometimes when working with particular third-party proprietary code which has incorrect using the keys order, we have to maintain the object keys in the same order of incoming JSON object, this package is useful for these cases.
Disclaimer: same as Go's default [map](https://blog.golang.org/go-maps-in-action)
Index ¶
- type KVPair
- type OrderedMap
- func (om *OrderedMap) Delete(key string) (value interface{}, ok bool)
- func (om *OrderedMap) EntriesIter() func() (*KVPair, bool)
- func (om *OrderedMap) EntriesReverseIter() func() (*KVPair, bool)
- func (om *OrderedMap) Get(key string) interface{}
- func (om *OrderedMap) GetMap() map[string]interface{}
- func (om *OrderedMap) GetValue(key string) (value interface{}, ok bool)
- func (om *OrderedMap) Has(key string) bool
- func (om *OrderedMap) MarshalJSON() (res []byte, err error)
- func (om *OrderedMap) Set(key string, value interface{})
- func (om *OrderedMap) UnmarshalJSON(data []byte) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type KVPair ¶
type KVPair struct { Key string Value interface{} }
the key-value pair type, for initializing from a list of key-value pairs, or for looping entries in the same order
type OrderedMap ¶
type OrderedMap struct {
// contains filtered or unexported fields
}
the OrderedMap type, has similar operations as the default map, but maintained the keys order of inserted; similar to map, all single key operations (Get/Set/Delete) runs at O(1).
func NewOrderedMapFromKVPairs ¶
func NewOrderedMapFromKVPairs(pairs []*KVPair) *OrderedMap
Create a new OrderedMap and populate from a list of key-value pairs
func (*OrderedMap) Delete ¶
func (om *OrderedMap) Delete(key string) (value interface{}, ok bool)
deletes the element with the specified key (m[key]) from the map. If there is no such element, this is a no-op.
func (*OrderedMap) EntriesIter ¶
func (om *OrderedMap) EntriesIter() func() (*KVPair, bool)
Iterate all key/value pairs in the same order of object constructed
func (*OrderedMap) EntriesReverseIter ¶
func (om *OrderedMap) EntriesReverseIter() func() (*KVPair, bool)
Iterate all key/value pairs in the reverse order of object constructed
Example ¶
// initialize from a list of key-value pairs om := NewOrderedMapFromKVPairs([]*KVPair{ {"country", "United States"}, {"countryCode", "US"}, {"region", "CA"}, {"regionName", "California"}, {"city", "Mountain View"}, {"zip", "94043"}, {"lat", 37.4192}, {"lon", -122.0574}, {"timezone", "America/Los_Angeles"}, {"isp", "Google Cloud"}, {"org", "Google Cloud"}, {"as", "AS15169 Google Inc."}, {"mobile", true}, {"proxy", false}, {"query", "35.192.xx.xxx"}, }) iter := om.EntriesReverseIter() for { pair, ok := iter() if !ok { break } fmt.Printf("%-12s: %v\n", pair.Key, pair.Value) }
Output: query : 35.192.xx.xxx proxy : false mobile : true as : AS15169 Google Inc. org : Google Cloud isp : Google Cloud timezone : America/Los_Angeles lon : -122.0574 lat : 37.4192 zip : 94043 city : Mountain View regionName : California region : CA countryCode : US country : United States
func (*OrderedMap) Get ¶
func (om *OrderedMap) Get(key string) interface{}
Get value for particular key, or nil if not exist; but don't rely on nil for non-exist; should check by Has or GetValue
func (*OrderedMap) GetValue ¶
func (om *OrderedMap) GetValue(key string) (value interface{}, ok bool)
Get value and exists together
func (*OrderedMap) MarshalJSON ¶
func (om *OrderedMap) MarshalJSON() (res []byte, err error)
this implements type json.Marshaler interface, so can be called in json.Marshal(om)
func (*OrderedMap) Set ¶
func (om *OrderedMap) Set(key string, value interface{})
set value for particular key, this will remember the order of keys inserted but if the key already exists, the order is not updated.
func (*OrderedMap) UnmarshalJSON ¶
func (om *OrderedMap) UnmarshalJSON(data []byte) error
this implements type json.Unmarshaler interface, so can be called in json.Unmarshal(data, om)
Example ¶
const jsonStream = `{ "country" : "United States", "countryCode" : "US", "region" : "CA", "regionName" : "California", "city" : "Mountain View", "zip" : "94043", "lat" : 37.4192, "lon" : -122.0574, "timezone" : "America/Los_Angeles", "isp" : "Google Cloud", "org" : "Google Cloud", "as" : "AS15169 Google Inc.", "mobile" : true, "proxy" : false, "query" : "35.192.xx.xxx" }` // compare with if using a regular generic map, the unmarshalled result // is a map with unpredictable order of keys var m map[string]interface{} err := json.Unmarshal([]byte(jsonStream), &m) if err != nil { fmt.Println("error:", err) } for key := range m { // fmt.Printf("%-12s: %v\n", key, m[key]) _ = key } // use the OrderedMap to Unmarshal from JSON object var om *OrderedMap = NewOrderedMap() err = json.Unmarshal([]byte(jsonStream), om) if err != nil { fmt.Println("error:", err) } // use an iterator func to loop over all key-value pairs, // it is ok to call Set append-modify new key-value pairs, // but not safe to call Delete during iteration. iter := om.EntriesIter() for { pair, ok := iter() if !ok { break } fmt.Printf("%-12s: %v\n", pair.Key, pair.Value) if pair.Key == "city" { om.Set("mobile", false) om.Set("extra", 42) } }
Output: country : United States countryCode : US region : CA regionName : California city : Mountain View zip : 94043 lat : 37.4192 lon : -122.0574 timezone : America/Los_Angeles isp : Google Cloud org : Google Cloud as : AS15169 Google Inc. mobile : false proxy : false query : 35.192.xx.xxx extra : 42