Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
18 changes: 14 additions & 4 deletions orderedmap.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package orderedmap

import (
"bytes"
"encoding/json"
"errors"
"sort"
Expand Down Expand Up @@ -42,17 +43,23 @@ func (a ByPair) Swap(i, j int) { a.Pairs[i], a.Pairs[j] = a.Pairs[j], a.Pai
func (a ByPair) Less(i, j int) bool { return a.LessFunc(a.Pairs[i], a.Pairs[j]) }

type OrderedMap struct {
keys []string
values map[string]interface{}
keys []string
values map[string]interface{}
escapeHTML bool
}

func New() *OrderedMap {
o := OrderedMap{}
o.keys = []string{}
o.values = map[string]interface{}{}
o.escapeHTML = true
return &o
}

func (o *OrderedMap) SetEscapeHTML(on bool) {
o.escapeHTML = on
}

func (o *OrderedMap) Get(key string) (interface{}, bool) {
val, exists := o.values[key]
return val, exists
Expand Down Expand Up @@ -315,11 +322,14 @@ func (o OrderedMap) MarshalJSON() ([]byte, error) {
s = s + `"` + kEscaped + `":`
// add value
v := o.values[k]
vBytes, err := json.Marshal(v)
buffer := new(bytes.Buffer)
encoder := json.NewEncoder(buffer)
encoder.SetEscapeHTML(o.escapeHTML)
err := encoder.Encode(v)
if err != nil {
return []byte{}, err
}
s = s + string(vBytes) + ","
s = s + buffer.String() + ","
}
if len(o.keys) > 0 {
s = s[0 : len(s)-1]
Expand Down
23 changes: 22 additions & 1 deletion orderedmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"sort"
"strings"
"testing"
)

Expand Down Expand Up @@ -113,6 +114,8 @@ func TestMarshalJSON(t *testing.T) {
o.Set("number", 3)
// string
o.Set("string", "x")
// string
o.Set("specialstring", "\\.<>[]{}_-")
// new value keeps key in old position
o.Set("number", 4)
// keys not sorted alphabetically
Expand All @@ -138,7 +141,7 @@ func TestMarshalJSON(t *testing.T) {
}
s := string(b)
// check json is correctly ordered
if s != `{"number":4,"string":"x","z":1,"a":2,"b":3,"slice":["1",1],"orderedmap":{"e":1,"a":2},"test\"ing":9}` {
if s != `{"number":4,"string":"x","specialstring":"\\.\u003c\u003e[]{}_-","z":1,"a":2,"b":3,"slice":["1",1],"orderedmap":{"e":1,"a":2},"test\"ing":9}` {
t.Error("JSON Marshal value is incorrect", s)
}
// convert to indented json
Expand All @@ -150,6 +153,7 @@ func TestMarshalJSON(t *testing.T) {
ei := `{
"number": 4,
"string": "x",
"specialstring": "\\.\u003c\u003e[]{}_-",
"z": 1,
"a": 2,
"b": 3,
Expand All @@ -170,6 +174,23 @@ func TestMarshalJSON(t *testing.T) {
}
}

func TestMarshalJSONNoEscapeHTML(t *testing.T) {
o := New()
o.SetEscapeHTML(false)
// string special characters
o.Set("specialstring", "\\.<>[]{}_-")
// convert to json
b, err := o.MarshalJSON()
if err != nil {
t.Error("Marshalling json", err)
}
s := strings.Replace(string(b), "\n", "", -1)
// check json is correctly ordered
if s != `{"specialstring":"\\.<>[]{}_-"}` {
t.Error("JSON Marshal value is incorrect", s)
}
}

func TestUnmarshalJSON(t *testing.T) {
s := `{
"number": 4,
Expand Down
10 changes: 8 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ func main() {
// use New() instead of o := map[string]interface{}{}
o := orderedmap.New()

// use SetEscapeHTML() to whether escape problematic HTML characters or not, defaults is true
o.SetEscapeHTML(false)

// use Set instead of o["a"] = 1
o.Set("a", 1)

// add some value with special characters
o.Set("b", "\\.<>[]{}_-")

// use Get instead of i, ok := o["a"]
val, ok := o.Get("a")

Expand All @@ -44,10 +50,10 @@ func main() {
// all maps (including nested maps) will be parsed as orderedmaps
s := `{"a": 1}`
err := json.Unmarshal([]byte(s), &o)

// sort the keys
o.SortKeys(sort.Strings)

// sort by Pair
o.Sort(func(a *Pair, b *Pair) bool {
return a.Value().(float64) < b.Value().(float64)
Expand Down