Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/Pexeso/orderedmap

go 1.17
47 changes: 26 additions & 21 deletions orderedmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ package orderedmap
import (
"bytes"
"encoding/json"
"errors"
"sort"
"strings"
)

var NoValueError = errors.New("No value for this key")

type KeyIndex struct {
Key string
Index int
}

type ByIndex []KeyIndex

var _ sort.Interface = &ByIndex{}

func (a ByIndex) Len() int { return len(a) }
func (a ByIndex) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByIndex) Less(i, j int) bool { return a[i].Index < a[j].Index }
Expand All @@ -38,6 +38,8 @@ type ByPair struct {
LessFunc func(a *Pair, j *Pair) bool
}

var _ sort.Interface = &ByPair{}

func (a ByPair) Len() int { return len(a.Pairs) }
func (a ByPair) Swap(i, j int) { a.Pairs[i], a.Pairs[j] = a.Pairs[j], a.Pairs[i] }
func (a ByPair) Less(i, j int) bool { return a.LessFunc(a.Pairs[i], a.Pairs[j]) }
Expand Down Expand Up @@ -99,12 +101,12 @@ func (o *OrderedMap) Keys() []string {
return o.keys
}

// SortKeys Sort the map keys using your sort func
// SortKeys sorts the map keys using your sort func
func (o *OrderedMap) SortKeys(sortFunc func(keys []string)) {
sortFunc(o.keys)
}

// Sort Sort the map using your sort func
// Sort sorts the map using your sort func
func (o *OrderedMap) Sort(lessFunc func(a *Pair, b *Pair) bool) {
pairs := make([]*Pair, len(o.keys))
for i, key := range o.keys {
Expand All @@ -118,28 +120,21 @@ func (o *OrderedMap) Sort(lessFunc func(a *Pair, b *Pair) bool) {
}
}

var _ json.Unmarshaler = &OrderedMap{}

// UnmarshalJSON implements the json.Unmarshaler interface for OrderedMap.
func (o *OrderedMap) UnmarshalJSON(b []byte) error {
if o.values == nil {
o.values = map[string]interface{}{}
}
var err error
err = mapStringToOrderedMap(string(b), o)
if err != nil {
return err
}
return nil
return mapStringToOrderedMap(string(b), o)
}

func unmarshalJSONUseNumber(s string, v interface{}) error {
r := strings.NewReader(s)
decoder := json.NewDecoder(r)
decoder.UseNumber()
err := decoder.Decode(v)
if err != nil {
return err
}

return nil
return decoder.Decode(v)
}

func mapStringToOrderedMap(s string, o *OrderedMap) error {
Expand Down Expand Up @@ -253,7 +248,7 @@ func mapStringToOrderedMap(s string, o *OrderedMap) error {
// this may be recursive if values in the slice are slices
if hasValidJson {
newSlice := []interface{}{}
err := sliceStringToSliceWithOrderedMaps(valueStr, &newSlice)
err := sliceStringToSliceWithOrderedMaps(valueStr, &newSlice, o.useNumber)
if err != nil {
return err
}
Expand All @@ -279,7 +274,7 @@ func mapStringToOrderedMap(s string, o *OrderedMap) error {
return nil
}

func sliceStringToSliceWithOrderedMaps(valueStr string, newSlice *[]interface{}) error {
func sliceStringToSliceWithOrderedMaps(valueStr string, newSlice *[]interface{}, useNumber bool) error {
// if the value for this key is a []interface, convert any map items to an orderedmap.
// find end of valueStr by removing everything after last ]
// until it forms valid json
Expand All @@ -297,14 +292,21 @@ func sliceStringToSliceWithOrderedMaps(valueStr string, newSlice *[]interface{})
endItem = endItem + 1
continue
}

// if this substring compiles to json, it's the next item
possibleItemStr := strings.TrimSpace(itemsStr[startItem:endItem])
var possibleItem interface{}
err := json.Unmarshal([]byte(possibleItemStr), &possibleItem)
var err error
if useNumber {
err = unmarshalJSONUseNumber(possibleItemStr, &possibleItem)
} else {
err = json.Unmarshal([]byte(possibleItemStr), &possibleItem)
}
if err != nil {
endItem = endItem + 1
continue
}

if possibleItemStr[0] == '{' {
// if item is map, convert to orderedmap
oo := New()
Expand All @@ -319,7 +321,7 @@ func sliceStringToSliceWithOrderedMaps(valueStr string, newSlice *[]interface{})
} else if possibleItemStr[0] == '[' {
// if item is slice, convert to slice with orderedmaps
newItem := []interface{}{}
err := sliceStringToSliceWithOrderedMaps(possibleItemStr, &newItem)
err := sliceStringToSliceWithOrderedMaps(possibleItemStr, &newItem, useNumber)
if err != nil {
return err
}
Expand All @@ -341,6 +343,9 @@ func sliceStringToSliceWithOrderedMaps(valueStr string, newSlice *[]interface{})
return nil
}

var _ json.Marshaler = &OrderedMap{}

// MarshalJSON implements the json.Marshaler interface for OrderedMap.
func (o OrderedMap) MarshalJSON() ([]byte, error) {
s := "{"
for _, k := range o.keys {
Expand Down
23 changes: 23 additions & 0 deletions orderedmap_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package orderedmap

import (
"bytes"
"encoding/json"
"fmt"
"math"
"sort"
"strings"
"testing"
Expand Down Expand Up @@ -530,3 +532,24 @@ func TestOrderedMap_empty_map(t *testing.T) {
t.Error("Got", marshalledStr)
}
}

func TestOrderedMap_uint64_slice_serialization(t *testing.T) {
uints := []uint64{math.MaxUint64, math.MaxUint64-100, math.MaxUint64-1000}

str1 := []byte(fmt.Sprintf(`{"key":[%d,%d,%d]}`, uints[0], uints[1], uints[2]))
om := New()
om.SetUseNumber(true)

if err := json.Unmarshal(str1, om); err != nil {
t.Fatal(err)
}

str2, err := json.Marshal(om)
if err != nil {
t.Fatal(err)
}

if !bytes.Equal(str1, str2) {
t.Fatalf("%s != %s", str1, str2)
}
}