From 0dcb10bcabf5e02c6eae40c07b586a5e4a2e7298 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 01:05:01 +0100 Subject: [PATCH 01/12] - JSON serialization for all lists --- containers/containers.go | 2 ++ containers/serialization.go | 17 ++++++++++ lists/arraylist/arraylist_test.go | 26 ++++++++++++++++ lists/arraylist/serialization.go | 29 +++++++++++++++++ .../doublylinkedlist/doublylinkedlist_test.go | 26 ++++++++++++++++ lists/doublylinkedlist/serialization.go | 31 +++++++++++++++++++ lists/singlylinkedlist/serialization.go | 31 +++++++++++++++++++ 7 files changed, 162 insertions(+) create mode 100644 containers/serialization.go create mode 100644 lists/arraylist/serialization.go create mode 100644 lists/doublylinkedlist/serialization.go create mode 100644 lists/singlylinkedlist/serialization.go diff --git a/containers/containers.go b/containers/containers.go index 91a57c7..c35ab36 100644 --- a/containers/containers.go +++ b/containers/containers.go @@ -9,6 +9,8 @@ // Iterators provide stateful iterators. // // Enumerable provides Ruby inspired (each, select, map, find, any?, etc.) container functions. +// +// Serialization provides serializers (marshalers) and deserializers (unmarshalers). package containers import "github.com/emirpasic/gods/utils" diff --git a/containers/serialization.go b/containers/serialization.go new file mode 100644 index 0000000..d7c90c8 --- /dev/null +++ b/containers/serialization.go @@ -0,0 +1,17 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package containers + +// JSONSerializer provides JSON serialization +type JSONSerializer interface { + // ToJSON outputs the JSON representation of containers's elements. + ToJSON() ([]byte, error) +} + +// JSONDeserializer provides JSON deserialization +type JSONDeserializer interface { + // FromJSON populates containers's elements from the input JSON representation. + FromJSON([]byte) error +} diff --git a/lists/arraylist/arraylist_test.go b/lists/arraylist/arraylist_test.go index 67317e0..58fd8b1 100644 --- a/lists/arraylist/arraylist_test.go +++ b/lists/arraylist/arraylist_test.go @@ -426,6 +426,32 @@ func TestListIteratorLast(t *testing.T) { } } +func TestListSerialization(t *testing.T) { + list := New() + list.Add("a", "b", "c") + + var err error + assert := func() { + if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := list.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := list.ToJSON() + assert() + + err = list.FromJSON(json) + assert() +} + func benchmarkGet(b *testing.B, list *List, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/lists/arraylist/serialization.go b/lists/arraylist/serialization.go new file mode 100644 index 0000000..2f283fb --- /dev/null +++ b/lists/arraylist/serialization.go @@ -0,0 +1,29 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package arraylist + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*List)(nil) + var _ containers.JSONDeserializer = (*List)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (list *List) ToJSON() ([]byte, error) { + return json.Marshal(list.elements[:list.size]) +} + +// FromJSON populates list's elements from the input JSON representation. +func (list *List) FromJSON(data []byte) error { + err := json.Unmarshal(data, &list.elements) + if err == nil { + list.size = len(list.elements) + } + return err +} diff --git a/lists/doublylinkedlist/doublylinkedlist_test.go b/lists/doublylinkedlist/doublylinkedlist_test.go index fa66344..5fea3d0 100644 --- a/lists/doublylinkedlist/doublylinkedlist_test.go +++ b/lists/doublylinkedlist/doublylinkedlist_test.go @@ -426,6 +426,32 @@ func TestListIteratorLast(t *testing.T) { } } +func TestListSerialization(t *testing.T) { + list := New() + list.Add("a", "b", "c") + + var err error + assert := func() { + if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := list.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := list.ToJSON() + assert() + + err = list.FromJSON(json) + assert() +} + func benchmarkGet(b *testing.B, list *List, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/lists/doublylinkedlist/serialization.go b/lists/doublylinkedlist/serialization.go new file mode 100644 index 0000000..6018d80 --- /dev/null +++ b/lists/doublylinkedlist/serialization.go @@ -0,0 +1,31 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package doublylinkedlist + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*List)(nil) + var _ containers.JSONDeserializer = (*List)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (list *List) ToJSON() ([]byte, error) { + return json.Marshal(list.Values()) +} + +// FromJSON populates list's elements from the input JSON representation. +func (list *List) FromJSON(data []byte) error { + elements := []interface{}{} + err := json.Unmarshal(data, &elements) + if err == nil { + list.Clear() + list.Add(elements...) + } + return err +} diff --git a/lists/singlylinkedlist/serialization.go b/lists/singlylinkedlist/serialization.go new file mode 100644 index 0000000..324f1d9 --- /dev/null +++ b/lists/singlylinkedlist/serialization.go @@ -0,0 +1,31 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package singlylinkedlist + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*List)(nil) + var _ containers.JSONDeserializer = (*List)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (list *List) ToJSON() ([]byte, error) { + return json.Marshal(list.Values()) +} + +// FromJSON populates list's elements from the input JSON representation. +func (list *List) FromJSON(data []byte) error { + elements := []interface{}{} + err := json.Unmarshal(data, &elements) + if err == nil { + list.Clear() + list.Add(elements...) + } + return err +} From 696bb0e577e405f90b4f1e508cd0b55d9bcbb91b Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 01:12:33 +0100 Subject: [PATCH 02/12] - JSON serialization for all lists (test for singly linked list) --- .../singlylinkedlist/singlylinkedlist_test.go | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lists/singlylinkedlist/singlylinkedlist_test.go b/lists/singlylinkedlist/singlylinkedlist_test.go index 0a45929..27daacc 100644 --- a/lists/singlylinkedlist/singlylinkedlist_test.go +++ b/lists/singlylinkedlist/singlylinkedlist_test.go @@ -345,6 +345,32 @@ func TestListIteratorFirst(t *testing.T) { } } +func TestListSerialization(t *testing.T) { + list := New() + list.Add("a", "b", "c") + + var err error + assert := func() { + if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := list.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := list.ToJSON() + assert() + + err = list.FromJSON(json) + assert() +} + func benchmarkGet(b *testing.B, list *List, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { From 50b47dce4b3f881f69c3287b868e7b1d98d77bc1 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 01:28:09 +0100 Subject: [PATCH 03/12] - JSON serialization for all sets --- sets/hashset/hashset_test.go | 26 ++++++++++++++++++++++++++ sets/hashset/serialization.go | 31 +++++++++++++++++++++++++++++++ sets/treeset/serialization.go | 31 +++++++++++++++++++++++++++++++ sets/treeset/treeset_test.go | 26 ++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 sets/hashset/serialization.go create mode 100644 sets/treeset/serialization.go diff --git a/sets/hashset/hashset_test.go b/sets/hashset/hashset_test.go index b868631..280a6b3 100644 --- a/sets/hashset/hashset_test.go +++ b/sets/hashset/hashset_test.go @@ -62,6 +62,32 @@ func TestSetRemove(t *testing.T) { } } +func TestSetSerialization(t *testing.T) { + set := New() + set.Add("a", "b", "c") + + var err error + assert := func() { + if actualValue, expectedValue := set.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue := set.Contains("a", "b", "c"); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := set.ToJSON() + assert() + + err = set.FromJSON(json) + assert() +} + func benchmarkContains(b *testing.B, set *Set, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/sets/hashset/serialization.go b/sets/hashset/serialization.go new file mode 100644 index 0000000..af7bfe8 --- /dev/null +++ b/sets/hashset/serialization.go @@ -0,0 +1,31 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hashset + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Set)(nil) + var _ containers.JSONDeserializer = (*Set)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (set *Set) ToJSON() ([]byte, error) { + return json.Marshal(set.Values()) +} + +// FromJSON populates list's elements from the input JSON representation. +func (set *Set) FromJSON(data []byte) error { + elements := []interface{}{} + err := json.Unmarshal(data, &elements) + if err == nil { + set.Clear() + set.Add(elements...) + } + return err +} diff --git a/sets/treeset/serialization.go b/sets/treeset/serialization.go new file mode 100644 index 0000000..10b1599 --- /dev/null +++ b/sets/treeset/serialization.go @@ -0,0 +1,31 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package treeset + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Set)(nil) + var _ containers.JSONDeserializer = (*Set)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (set *Set) ToJSON() ([]byte, error) { + return json.Marshal(set.Values()) +} + +// FromJSON populates list's elements from the input JSON representation. +func (set *Set) FromJSON(data []byte) error { + elements := []interface{}{} + err := json.Unmarshal(data, &elements) + if err == nil { + set.Clear() + set.Add(elements...) + } + return err +} diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index 881adc2..0f4b667 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -327,6 +327,32 @@ func TestSetIteratorLast(t *testing.T) { } } +func TestSetSerialization(t *testing.T) { + set := NewWithStringComparator() + set.Add("a", "b", "c") + + var err error + assert := func() { + if actualValue, expectedValue := set.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue := set.Contains("a", "b", "c"); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := set.ToJSON() + assert() + + err = set.FromJSON(json) + assert() +} + func benchmarkContains(b *testing.B, set *Set, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { From 0887bbc9f45364c1ff57984c2103e4d6f1e6dcd4 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 03:40:29 +0100 Subject: [PATCH 04/12] - ToString function to convert to string from any type --- utils/utils.go | 37 ++++++++++++++++ utils/utils_test.go | 104 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 utils/utils_test.go diff --git a/utils/utils.go b/utils/utils.go index 120f1a7..1ad49cb 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -8,3 +8,40 @@ // - sorting // - comparators package utils + +import ( + "fmt" + "strconv" +) + +// ToString converts a value to string. +func ToString(value interface{}) string { + switch value.(type) { + case string: + return value.(string) + case int8: + return strconv.FormatInt(int64(value.(int8)), 10) + case int16: + return strconv.FormatInt(int64(value.(int16)), 10) + case int32: + return strconv.FormatInt(int64(value.(int32)), 10) + case int64: + return strconv.FormatInt(int64(value.(int64)), 10) + case uint8: + return strconv.FormatUint(uint64(value.(uint8)), 10) + case uint16: + return strconv.FormatUint(uint64(value.(uint16)), 10) + case uint32: + return strconv.FormatUint(uint64(value.(uint32)), 10) + case uint64: + return strconv.FormatUint(uint64(value.(uint64)), 10) + case float32: + return strconv.FormatFloat(float64(value.(float32)), 'g', -1, 64) + case float64: + return strconv.FormatFloat(float64(value.(float64)), 'g', -1, 64) + case bool: + return strconv.FormatBool(value.(bool)) + default: + return fmt.Sprintf("%+v", value) + } +} diff --git a/utils/utils_test.go b/utils/utils_test.go new file mode 100644 index 0000000..f5b3edc --- /dev/null +++ b/utils/utils_test.go @@ -0,0 +1,104 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package utils + +import ( + "strings" + "testing" +) + +func TestToStringInts(t *testing.T) { + var value interface{} + + value = int8(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + value = int16(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + value = int32(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + value = int64(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + value = rune(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } +} + +func TestToStringUInts(t *testing.T) { + var value interface{} + + value = uint8(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + value = uint16(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + value = uint32(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + value = uint64(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + value = byte(1) + if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } +} + +func TestToStringFloats(t *testing.T) { + var value interface{} + + value = float32(1.123456) + if actualValue, expectedValue := ToString(value), "1.123456"; !strings.HasPrefix(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + value = float32(1.123456) + if actualValue, expectedValue := ToString(value), "1.123456"; !strings.HasPrefix(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } +} + +func TestToStringOther(t *testing.T) { + var value interface{} + + value = "abc" + if actualValue, expectedValue := ToString(value), "abc"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + value = true + if actualValue, expectedValue := ToString(value), "true"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + type T struct { + id int + name string + } + + if actualValue, expectedValue := ToString(T{1, "abc"}), "{id:1 name:abc}"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } +} From 706042c8bc192ff5e6e098cb85a3b78617145615 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 03:44:02 +0100 Subject: [PATCH 05/12] - hash map (de)serialization --- maps/hashmap/hashmap_test.go | 31 ++++++++++++++++++++++++++++ maps/hashmap/serialization.go | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 maps/hashmap/serialization.go diff --git a/maps/hashmap/hashmap_test.go b/maps/hashmap/hashmap_test.go index 119e9ed..7122574 100644 --- a/maps/hashmap/hashmap_test.go +++ b/maps/hashmap/hashmap_test.go @@ -118,6 +118,37 @@ func TestMapRemove(t *testing.T) { } } +func TestMapSerialization(t *testing.T) { + m := New() + m.Put("a", 1.0) + m.Put("b", 2.0) + m.Put("c", 3.0) + + var err error + assert := func() { + if actualValue, expectedValue := m.Keys(), []interface{}{"a", "b", "c"}; !sameElements(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := m.Values(), []interface{}{1.0, 2.0, 3.0}; !sameElements(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := m.ToJSON() + assert() + + err = m.FromJSON(json) + assert() +} + func sameElements(a []interface{}, b []interface{}) bool { if len(a) != len(b) { return false diff --git a/maps/hashmap/serialization.go b/maps/hashmap/serialization.go new file mode 100644 index 0000000..b8e9026 --- /dev/null +++ b/maps/hashmap/serialization.go @@ -0,0 +1,38 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hashmap + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" + "github.com/emirpasic/gods/utils" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Map)(nil) + var _ containers.JSONDeserializer = (*Map)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (m *Map) ToJSON() ([]byte, error) { + elements := make(map[string]interface{}) + for key, value := range m.m { + elements[utils.ToString(key)] = value + } + return json.Marshal(&elements) +} + +// FromJSON populates list's elements from the input JSON representation. +func (m *Map) FromJSON(data []byte) error { + elements := make(map[string]interface{}) + err := json.Unmarshal(data, &elements) + if err == nil { + m.Clear() + for key, value := range elements { + m.m[key] = value + } + } + return err +} From b3ac670248db667ea35cba6571b6484ca49d52ce Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 03:49:30 +0100 Subject: [PATCH 06/12] - all stacks (de)serialization --- stacks/arraystack/arraystack_test.go | 29 +++++++++++++++++++ stacks/arraystack/serialization.go | 22 ++++++++++++++ .../linkedliststack/linkedliststack_test.go | 29 +++++++++++++++++++ stacks/linkedliststack/serialization.go | 22 ++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 stacks/arraystack/serialization.go create mode 100644 stacks/linkedliststack/serialization.go diff --git a/stacks/arraystack/arraystack_test.go b/stacks/arraystack/arraystack_test.go index 48f6be4..62ba7fd 100644 --- a/stacks/arraystack/arraystack_test.go +++ b/stacks/arraystack/arraystack_test.go @@ -5,6 +5,7 @@ package arraystack import ( + "fmt" "testing" ) @@ -231,6 +232,34 @@ func TestStackIteratorLast(t *testing.T) { } } +func TestStackSerialization(t *testing.T) { + stack := New() + stack.Push("a") + stack.Push("b") + stack.Push("c") + + var err error + assert := func() { + if actualValue, expectedValue := fmt.Sprintf("%s%s%s", stack.Values()...), "cba"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := stack.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := stack.ToJSON() + assert() + + err = stack.FromJSON(json) + assert() +} + func benchmarkPush(b *testing.B, stack *Stack, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/stacks/arraystack/serialization.go b/stacks/arraystack/serialization.go new file mode 100644 index 0000000..d1ad81d --- /dev/null +++ b/stacks/arraystack/serialization.go @@ -0,0 +1,22 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package arraystack + +import "github.com/emirpasic/gods/containers" + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Stack)(nil) + var _ containers.JSONDeserializer = (*Stack)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (stack *Stack) ToJSON() ([]byte, error) { + return stack.list.ToJSON() +} + +// FromJSON populates list's elements from the input JSON representation. +func (stack *Stack) FromJSON(data []byte) error { + return stack.list.FromJSON(data) +} diff --git a/stacks/linkedliststack/linkedliststack_test.go b/stacks/linkedliststack/linkedliststack_test.go index 8fb0f43..f7b6f95 100644 --- a/stacks/linkedliststack/linkedliststack_test.go +++ b/stacks/linkedliststack/linkedliststack_test.go @@ -5,6 +5,7 @@ package linkedliststack import ( + "fmt" "testing" ) @@ -147,6 +148,34 @@ func TestStackIteratorFirst(t *testing.T) { } } +func TestStackSerialization(t *testing.T) { + stack := New() + stack.Push("a") + stack.Push("b") + stack.Push("c") + + var err error + assert := func() { + if actualValue, expectedValue := fmt.Sprintf("%s%s%s", stack.Values()...), "cba"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := stack.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := stack.ToJSON() + assert() + + err = stack.FromJSON(json) + assert() +} + func benchmarkPush(b *testing.B, stack *Stack, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/stacks/linkedliststack/serialization.go b/stacks/linkedliststack/serialization.go new file mode 100644 index 0000000..ac6a68c --- /dev/null +++ b/stacks/linkedliststack/serialization.go @@ -0,0 +1,22 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package linkedliststack + +import "github.com/emirpasic/gods/containers" + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Stack)(nil) + var _ containers.JSONDeserializer = (*Stack)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (stack *Stack) ToJSON() ([]byte, error) { + return stack.list.ToJSON() +} + +// FromJSON populates list's elements from the input JSON representation. +func (stack *Stack) FromJSON(data []byte) error { + return stack.list.FromJSON(data) +} From 911a9d76cfef31d4a337106453e858601c269057 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 03:55:12 +0100 Subject: [PATCH 07/12] - hash bidi map (de)serialization --- maps/hashbidimap/hashbidimap_test.go | 31 ++++++++++++++++++++++++++ maps/hashbidimap/serialization.go | 33 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 maps/hashbidimap/serialization.go diff --git a/maps/hashbidimap/hashbidimap_test.go b/maps/hashbidimap/hashbidimap_test.go index 5527a03..96e4688 100644 --- a/maps/hashbidimap/hashbidimap_test.go +++ b/maps/hashbidimap/hashbidimap_test.go @@ -150,6 +150,37 @@ func TestMapGetKey(t *testing.T) { } } +func TestMapSerialization(t *testing.T) { + m := New() + m.Put("a", 1.0) + m.Put("b", 2.0) + m.Put("c", 3.0) + + var err error + assert := func() { + if actualValue, expectedValue := m.Keys(), []interface{}{"a", "b", "c"}; !sameElements(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := m.Values(), []interface{}{1.0, 2.0, 3.0}; !sameElements(actualValue, expectedValue) { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := m.ToJSON() + assert() + + err = m.FromJSON(json) + assert() +} + func sameElements(a []interface{}, b []interface{}) bool { if len(a) != len(b) { return false diff --git a/maps/hashbidimap/serialization.go b/maps/hashbidimap/serialization.go new file mode 100644 index 0000000..9f6247e --- /dev/null +++ b/maps/hashbidimap/serialization.go @@ -0,0 +1,33 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hashbidimap + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Map)(nil) + var _ containers.JSONDeserializer = (*Map)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (m *Map) ToJSON() ([]byte, error) { + return m.forwardMap.ToJSON() +} + +// FromJSON populates list's elements from the input JSON representation. +func (m *Map) FromJSON(data []byte) error { + elements := make(map[string]interface{}) + err := json.Unmarshal(data, &elements) + if err == nil { + m.Clear() + for key, value := range elements { + m.Put(key, value) + } + } + return err +} From 7eadb02f45042e48774e0e4d7fd14dcfade0f103 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 04:18:23 +0100 Subject: [PATCH 08/12] - all trees (de)serialization --- trees/avltree/avltree_test.go | 31 ++++++++++++++++++++ trees/avltree/serialization.go | 39 +++++++++++++++++++++++++ trees/binaryheap/binaryheap_test.go | 32 ++++++++++++++++++++ trees/binaryheap/serialization.go | 22 ++++++++++++++ trees/btree/btree_test.go | 31 ++++++++++++++++++++ trees/btree/serialization.go | 39 +++++++++++++++++++++++++ trees/redblacktree/redblacktree_test.go | 31 ++++++++++++++++++++ trees/redblacktree/serialization.go | 39 +++++++++++++++++++++++++ 8 files changed, 264 insertions(+) create mode 100644 trees/avltree/serialization.go create mode 100644 trees/binaryheap/serialization.go create mode 100644 trees/btree/serialization.go create mode 100644 trees/redblacktree/serialization.go diff --git a/trees/avltree/avltree_test.go b/trees/avltree/avltree_test.go index 2e791d2..99c2adf 100644 --- a/trees/avltree/avltree_test.go +++ b/trees/avltree/avltree_test.go @@ -556,6 +556,37 @@ func TestAVLTreeIteratorLast(t *testing.T) { } } +func TestAVLTreeSerialization(t *testing.T) { + tree := NewWithStringComparator() + tree.Put("c", "3") + tree.Put("b", "2") + tree.Put("a", "1") + + var err error + assert := func() { + if actualValue, expectedValue := tree.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue := tree.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" { + t.Errorf("Got %v expected %v", actualValue, "[a,b,c]") + } + if actualValue := tree.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" { + t.Errorf("Got %v expected %v", actualValue, "[1,2,3]") + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := tree.ToJSON() + assert() + + err = tree.FromJSON(json) + assert() +} + func benchmarkGet(b *testing.B, tree *Tree, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/trees/avltree/serialization.go b/trees/avltree/serialization.go new file mode 100644 index 0000000..0630d87 --- /dev/null +++ b/trees/avltree/serialization.go @@ -0,0 +1,39 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package avltree + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" + "github.com/emirpasic/gods/utils" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Tree)(nil) + var _ containers.JSONDeserializer = (*Tree)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (tree *Tree) ToJSON() ([]byte, error) { + elements := make(map[string]interface{}) + it := tree.Iterator() + for it.Next() { + elements[utils.ToString(it.Key())] = it.Value() + } + return json.Marshal(&elements) +} + +// FromJSON populates list's elements from the input JSON representation. +func (tree *Tree) FromJSON(data []byte) error { + elements := make(map[string]interface{}) + err := json.Unmarshal(data, &elements) + if err == nil { + tree.Clear() + for key, value := range elements { + tree.Put(key, value) + } + } + return err +} diff --git a/trees/binaryheap/binaryheap_test.go b/trees/binaryheap/binaryheap_test.go index a20d647..cf97813 100644 --- a/trees/binaryheap/binaryheap_test.go +++ b/trees/binaryheap/binaryheap_test.go @@ -259,6 +259,38 @@ func TestBinaryHeapIteratorLast(t *testing.T) { } } +func TestBinaryHeapSerialization(t *testing.T) { + heap := NewWithStringComparator() + + heap.Push("c") // ["c"] + heap.Push("b") // ["b","c"] + heap.Push("a") // ["a","c","b"]("b" swapped with "a", hence last) + + var err error + assert := func() { + if actualValue := heap.Values(); actualValue[0].(string) != "a" || actualValue[1].(string) != "c" || actualValue[2].(string) != "b" { + t.Errorf("Got %v expected %v", actualValue, "[1,3,2]") + } + if actualValue := heap.Size(); actualValue != 3 { + t.Errorf("Got %v expected %v", actualValue, 3) + } + if actualValue, ok := heap.Peek(); actualValue != "a" || !ok { + t.Errorf("Got %v expected %v", actualValue, "a") + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := heap.ToJSON() + assert() + + err = heap.FromJSON(json) + assert() +} + func benchmarkPush(b *testing.B, heap *Heap, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/trees/binaryheap/serialization.go b/trees/binaryheap/serialization.go new file mode 100644 index 0000000..299319b --- /dev/null +++ b/trees/binaryheap/serialization.go @@ -0,0 +1,22 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package binaryheap + +import "github.com/emirpasic/gods/containers" + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Heap)(nil) + var _ containers.JSONDeserializer = (*Heap)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (heap *Heap) ToJSON() ([]byte, error) { + return heap.list.ToJSON() +} + +// FromJSON populates list's elements from the input JSON representation. +func (heap *Heap) FromJSON(data []byte) error { + return heap.list.FromJSON(data) +} diff --git a/trees/btree/btree_test.go b/trees/btree/btree_test.go index 4705bc1..4d69665 100644 --- a/trees/btree/btree_test.go +++ b/trees/btree/btree_test.go @@ -1074,6 +1074,37 @@ func assertValidTreeNode(t *testing.T, node *Node, expectedEntries int, expected } } +func TestBTreeSerialization(t *testing.T) { + tree := NewWithStringComparator(3) + tree.Put("c", "3") + tree.Put("b", "2") + tree.Put("a", "1") + + var err error + assert := func() { + if actualValue, expectedValue := tree.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue := tree.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" { + t.Errorf("Got %v expected %v", actualValue, "[a,b,c]") + } + if actualValue := tree.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" { + t.Errorf("Got %v expected %v", actualValue, "[1,2,3]") + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := tree.ToJSON() + assert() + + err = tree.FromJSON(json) + assert() +} + func benchmarkGet(b *testing.B, tree *Tree, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/trees/btree/serialization.go b/trees/btree/serialization.go new file mode 100644 index 0000000..95c817e --- /dev/null +++ b/trees/btree/serialization.go @@ -0,0 +1,39 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package btree + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" + "github.com/emirpasic/gods/utils" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Tree)(nil) + var _ containers.JSONDeserializer = (*Tree)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (tree *Tree) ToJSON() ([]byte, error) { + elements := make(map[string]interface{}) + it := tree.Iterator() + for it.Next() { + elements[utils.ToString(it.Key())] = it.Value() + } + return json.Marshal(&elements) +} + +// FromJSON populates list's elements from the input JSON representation. +func (tree *Tree) FromJSON(data []byte) error { + elements := make(map[string]interface{}) + err := json.Unmarshal(data, &elements) + if err == nil { + tree.Clear() + for key, value := range elements { + tree.Put(key, value) + } + } + return err +} diff --git a/trees/redblacktree/redblacktree_test.go b/trees/redblacktree/redblacktree_test.go index 714defc..74c3d8a 100644 --- a/trees/redblacktree/redblacktree_test.go +++ b/trees/redblacktree/redblacktree_test.go @@ -557,6 +557,37 @@ func TestRedBlackTreeIteratorLast(t *testing.T) { } } +func TestRedBlackTreeSerialization(t *testing.T) { + tree := NewWithStringComparator() + tree.Put("c", "3") + tree.Put("b", "2") + tree.Put("a", "1") + + var err error + assert := func() { + if actualValue, expectedValue := tree.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue := tree.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" { + t.Errorf("Got %v expected %v", actualValue, "[a,b,c]") + } + if actualValue := tree.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" { + t.Errorf("Got %v expected %v", actualValue, "[1,2,3]") + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := tree.ToJSON() + assert() + + err = tree.FromJSON(json) + assert() +} + func benchmarkGet(b *testing.B, tree *Tree, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/trees/redblacktree/serialization.go b/trees/redblacktree/serialization.go new file mode 100644 index 0000000..7969fc5 --- /dev/null +++ b/trees/redblacktree/serialization.go @@ -0,0 +1,39 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package redblacktree + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" + "github.com/emirpasic/gods/utils" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Tree)(nil) + var _ containers.JSONDeserializer = (*Tree)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (tree *Tree) ToJSON() ([]byte, error) { + elements := make(map[string]interface{}) + it := tree.Iterator() + for it.Next() { + elements[utils.ToString(it.Key())] = it.Value() + } + return json.Marshal(&elements) +} + +// FromJSON populates list's elements from the input JSON representation. +func (tree *Tree) FromJSON(data []byte) error { + elements := make(map[string]interface{}) + err := json.Unmarshal(data, &elements) + if err == nil { + tree.Clear() + for key, value := range elements { + tree.Put(key, value) + } + } + return err +} From 232f8d8a62b386dd2a8a51880b7162f31b84ee23 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 04:35:57 +0100 Subject: [PATCH 09/12] - tree-map and tree-bidi-map (de)serialization --- maps/treebidimap/serialization.go | 39 ++++++++++++++++++++++++++++ maps/treebidimap/treebidimap_test.go | 31 ++++++++++++++++++++++ maps/treemap/serialization.go | 22 ++++++++++++++++ maps/treemap/treemap_test.go | 31 ++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 maps/treebidimap/serialization.go create mode 100644 maps/treemap/serialization.go diff --git a/maps/treebidimap/serialization.go b/maps/treebidimap/serialization.go new file mode 100644 index 0000000..f9a7850 --- /dev/null +++ b/maps/treebidimap/serialization.go @@ -0,0 +1,39 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package treebidimap + +import ( + "encoding/json" + "github.com/emirpasic/gods/containers" + "github.com/emirpasic/gods/utils" +) + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Map)(nil) + var _ containers.JSONDeserializer = (*Map)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (m *Map) ToJSON() ([]byte, error) { + elements := make(map[string]interface{}) + it := m.Iterator() + for it.Next() { + elements[utils.ToString(it.Key())] = it.Value() + } + return json.Marshal(&elements) +} + +// FromJSON populates list's elements from the input JSON representation. +func (m *Map) FromJSON(data []byte) error { + elements := make(map[string]interface{}) + err := json.Unmarshal(data, &elements) + if err == nil { + m.Clear() + for key, value := range elements { + m.Put(key, value) + } + } + return err +} diff --git a/maps/treebidimap/treebidimap_test.go b/maps/treebidimap/treebidimap_test.go index c504e97..0ef5165 100644 --- a/maps/treebidimap/treebidimap_test.go +++ b/maps/treebidimap/treebidimap_test.go @@ -473,6 +473,37 @@ func TestMapIteratorLast(t *testing.T) { } } +func TestMapSerialization(t *testing.T) { + m := NewWithStringComparators() + m.Put("a", "1") + m.Put("b", "2") + m.Put("c", "3") + + var err error + assert := func() { + if actualValue := m.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" { + t.Errorf("Got %v expected %v", actualValue, "[a,b,c]") + } + if actualValue := m.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" { + t.Errorf("Got %v expected %v", actualValue, "[1,2,3]") + } + if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := m.ToJSON() + assert() + + err = m.FromJSON(json) + assert() +} + func benchmarkGet(b *testing.B, m *Map, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { diff --git a/maps/treemap/serialization.go b/maps/treemap/serialization.go new file mode 100644 index 0000000..25f4a6f --- /dev/null +++ b/maps/treemap/serialization.go @@ -0,0 +1,22 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package treemap + +import "github.com/emirpasic/gods/containers" + +func assertSerializationImplementation() { + var _ containers.JSONSerializer = (*Map)(nil) + var _ containers.JSONDeserializer = (*Map)(nil) +} + +// ToJSON outputs the JSON representation of list's elements. +func (m *Map) ToJSON() ([]byte, error) { + return m.tree.ToJSON() +} + +// FromJSON populates list's elements from the input JSON representation. +func (m *Map) FromJSON(data []byte) error { + return m.tree.FromJSON(data) +} diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 0039601..a73e873 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -440,6 +440,37 @@ func TestMapIteratorLast(t *testing.T) { } } +func TestMapSerialization(t *testing.T) { + m := NewWithStringComparator() + m.Put("a", "1") + m.Put("b", "2") + m.Put("c", "3") + + var err error + assert := func() { + if actualValue := m.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" { + t.Errorf("Got %v expected %v", actualValue, "[a,b,c]") + } + if actualValue := m.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" { + t.Errorf("Got %v expected %v", actualValue, "[1,2,3]") + } + if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if err != nil { + t.Errorf("Got error %v", err) + } + } + + assert() + + json, err := m.ToJSON() + assert() + + err = m.FromJSON(json) + assert() +} + func benchmarkGet(b *testing.B, m *Map, size int) { for i := 0; i < b.N; i++ { for n := 0; n < size; n++ { From 42d0c04ae7629ca4645c4d548f9335396229a2ff Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 04:58:03 +0100 Subject: [PATCH 10/12] - serialization example --- examples/serialization.go | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 examples/serialization.go diff --git a/examples/serialization.go b/examples/serialization.go new file mode 100644 index 0000000..72a1ebf --- /dev/null +++ b/examples/serialization.go @@ -0,0 +1,51 @@ +package examples + +import ( + "fmt" + "github.com/emirpasic/gods/lists/arraylist" + "github.com/emirpasic/gods/maps/hashmap" +) + +// ListSerializationExample demonstrates how to serialize and deserialize lists to and from JSON +func ListSerializationExample() { + list := arraylist.New() + list.Add("a", "b", "c") + + // Serialization (marshalling) + json, err := list.ToJSON() + if err != nil { + fmt.Println(err) + } + fmt.Println(string(json)) // ["a","b","c"] + + // Deserialization (unmarshalling) + json = []byte(`["a","b"]`) + err = list.FromJSON(json) + if err != nil { + fmt.Println(err) + } + fmt.Println(list) // ArrayList ["a","b"] +} + +// MapSerializationExample demonstrates how to serialize and deserialize maps to and from JSON +func MapSerializationExample() { + m := hashmap.New() + m.Put("a", "1") + m.Put("b", "2") + m.Put("c", "3") + + // Serialization (marshalling) + json, err := m.ToJSON() + if err != nil { + fmt.Println(err) + } + fmt.Println(string(json)) // {"a":"1","b":"2","c":"3"} + + // Deserialization (unmarshalling) + json = []byte(`{"a":"1","b":"2"}`) + err = m.FromJSON(json) + if err != nil { + fmt.Println(err) + } + fmt.Println(m) // HashMap {"a":"1","b":"2"} +} From 2752136e4c76b410502ff5979067ea7a2c95b960 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 05:18:15 +0100 Subject: [PATCH 11/12] - update documentation on serialization --- README.md | 130 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 115 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 9881cee..cdc1830 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,9 @@ Implementation of various data structures and algorithms in Go. - [Enumerable](#enumerable) - [EnumerableWithIndex](#enumerablewithindex) - [EnumerableWithKey](#enumerablewithkey) + - [Serialization](#serialization) + - [JSONSerializer](#jsonserializer) + - [JSONDeserializer](#jsondeserializer) - [Sort](#sort) - [Container](#container) - [Appendix](#appendix) @@ -104,7 +107,7 @@ type List interface { A [list](#lists) backed by a dynamic array that grows and shrinks implicitly. -Implements [List](#lists), [IteratorWithIndex](#iteratorwithindex) and [EnumerableWithIndex](#enumerablewithindex) interfaces. +Implements [List](#lists), [IteratorWithIndex](#iteratorwithindex), [EnumerableWithIndex](#enumerablewithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -141,7 +144,7 @@ func main() { A [list](#lists) where each element points to the next element in the list. -Implements [List](#lists), [IteratorWithIndex](#iteratorwithindex) and [EnumerableWithIndex](#enumerablewithindex) interfaces. +Implements [List](#lists), [IteratorWithIndex](#iteratorwithindex), [EnumerableWithIndex](#enumerablewithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -178,7 +181,7 @@ func main() { A [list](#lists) where each element points to the next and previous elements in the list. -Implements [List](#lists), [IteratorWithIndex](#iteratorwithindex) and [EnumerableWithIndex](#enumerablewithindex) interfaces. +Implements [List](#lists), [IteratorWithIndex](#iteratorwithindex), [EnumerableWithIndex](#enumerablewithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -235,7 +238,7 @@ type Set interface { A [set](#sets) backed by a hash table (actually a Go's map). It makes no guarantees as to the iteration order of the set. -Implements [Set](#sets) interface. +Implements [Set](#sets), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -262,7 +265,7 @@ func main() { A [set](#sets) backed by a [red-black tree](#redblacktree) to keep the elements ordered with respect to the [comparator](#comparator). -Implements [Set](#sets), [IteratorWithIndex](#iteratorwithindex) and [EnumerableWithIndex](#enumerablewithindex) interfaces. +Implements [Set](#sets), [IteratorWithIndex](#iteratorwithindex), [EnumerableWithIndex](#enumerablewithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -309,7 +312,7 @@ type Stack interface { A [stack](#stacks) based on a [linked list](#singlylinkedlist). -Implements [Stack](#stacks) and [IteratorWithIndex](#iteratorwithindex) interfaces. +Implements [Stack](#stacks), [IteratorWithIndex](#iteratorwithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -336,7 +339,7 @@ func main() { A [stack](#stacks) based on a [array list](#arraylist). -Implements [Stack](#stacks) and [IteratorWithIndex](#iteratorwithindex) interfaces. +Implements [Stack](#stacks), [IteratorWithIndex](#iteratorwithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -394,7 +397,7 @@ type BidiMap interface { A [map](#maps) based on hash tables. Keys are unordered. -Implements [Map](#maps) interface. +Implements [Map](#maps), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -421,7 +424,7 @@ func main() { A [map](#maps) based on [red-black tree](#redblacktree). Keys are ordered ordered with respect to the [comparator](#comparator). -Implements [Map](#maps), [IteratorWithKey](#iteratorwithkey) and [EnumerableWithKey](#enumerablewithkey) interfaces. +Implements [Map](#maps), [IteratorWithKey](#iteratorwithkey), [EnumerableWithKey](#enumerablewithkey), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -452,7 +455,7 @@ func main() { A [map](#maps) based on two hashmaps. Keys are unordered. -Implements [BidiMap](#maps) interface. +Implements [BidiMap](#maps), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -481,7 +484,7 @@ func main() { A [map](#maps) based on red-black tree. This map guarantees that the map will be in both ascending key and value order. Other than key and value ordering, the goal with this structure is to avoid duplication of elements (unlike in [HashBidiMap](#hashbidimap)), which can be significant if contained elements are large. -Implements [BidiMap](#maps), [IteratorWithKey](#iteratorwithkey) and [EnumerableWithKey](#enumerablewithkey) interfaces. +Implements [BidiMap](#maps), [IteratorWithKey](#iteratorwithkey), [EnumerableWithKey](#enumerablewithkey), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces. ```go package main @@ -531,7 +534,7 @@ A red–black [tree](#trees) is a binary search tree with an extra bit of data p The balancing of the tree is not perfect but it is good enough to allow it to guarantee searching in O(log n) time, where n is the total number of elements in the tree. The insertion and deletion operations, along with the tree rearrangement and recoloring, are also performed in O(log n) time. [Wikipedia](http://en.wikipedia.org/wiki/Red%E2%80%93black_tree) -Implements [Tree](#trees) and [ReverseIteratorWithKey](#reverseiteratorwithkey) interfaces. +Implements [Tree](#trees), [ReverseIteratorWithKey](#reverseiteratorwithkey), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.

@@ -597,7 +600,7 @@ AVL [tree](#trees) is a self-balancing binary search tree. In an AVL tree, the h AVL trees are often compared with red–black trees because both support the same set of operations and take O(log n) time for the basic operations. For lookup-intensive applications, AVL trees are faster than red–black trees because they are more strictly balanced. [Wikipedia](https://en.wikipedia.org/wiki/AVL_tree) -Implements [Tree](#trees) and [ReverseIteratorWithKey](#reverseiteratorwithkey) interfaces. +Implements [Tree](#trees), [ReverseIteratorWithKey](#reverseiteratorwithkey), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.


AVL tree with balance factors (green)

@@ -664,7 +667,7 @@ According to Knuth's definition, a B-tree of order m is a tree which satisfies t Each internal node’s keys act as separation values which divide its subtrees. For example, if an internal node has 3 child nodes (or subtrees) then it must have 2 keys: a1 and a2. All values in the leftmost subtree will be less than a1, all values in the middle subtree will be between a1 and a2, and all values in the rightmost subtree will be greater than a2.[Wikipedia](http://en.wikipedia.org/wiki/Red%E2%80%93black_tree) -Implements [Tree](#trees) and [ReverseIteratorWithKey](#reverseiteratorwithkey) interfaces. +Implements [Tree](#trees), [ReverseIteratorWithKey](#reverseiteratorwithkey), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.

@@ -736,7 +739,7 @@ A binary heap is a [tree](#trees) created using a binary tree. It can be seen as All nodes are either greater than or equal to or less than or equal to each of its children, according to a comparison predicate defined for the heap. [Wikipedia](http://en.wikipedia.org/wiki/Binary_heap) -Implements [Tree](#trees) and [ReverseIteratorWithIndex](#reverseiteratorwithindex) interfaces. +Implements [Tree](#trees), [ReverseIteratorWithIndex](#reverseiteratorwithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.

@@ -1214,6 +1217,103 @@ func main() { } ``` +### Serialization + +All data structures can be serialized (marshalled) and deserialized (unmarshalled). Currently only JSON support is available. + +#### JSONSerializer + +Outputs the container into its JSON representation. + +Typical usage for key-value structures: +```go +package main + +import ( + "fmt" + "github.com/emirpasic/gods/maps/hashmap" +) + +func main() { + m := hashmap.New() + m.Put("a", "1") + m.Put("b", "2") + m.Put("c", "3") + + json, err := m.ToJSON() + if err != nil { + fmt.Println(err) + } + fmt.Println(string(json)) // {"a":"1","b":"2","c":"3"} +``` + +Typical usage for value-only structures: +```go +package main + +import ( + "fmt" + "github.com/emirpasic/gods/lists/arraylist" +) + +func main() { + list := arraylist.New() + list.Add("a", "b", "c") + + json, err := list.ToJSON() + if err != nil { + fmt.Println(err) + } + fmt.Println(string(json)) // ["a","b","c"] +} +``` + +#### JSONDeserializer + +Populates the container with elements from the input JSON representation. + +Typical usage for key-value structures: +```go +package main + +import ( + "fmt" + "github.com/emirpasic/gods/lists/arraylist" +) + +func main() { + list := arraylist.New() + + json := []byte(`["a","b"]`) + err := list.FromJSON(json) + if err != nil { + fmt.Println(err) + } + fmt.Println(list) // ArrayList ["a","b"] +} +``` + +Typical usage for value-only structures: +```go +package main + +import ( + "fmt" + "github.com/emirpasic/gods/lists/arraylist" +) + +func main() { + list := arraylist.New() + list.Add("a", "b", "c") + + json, err := list.ToJSON() + if err != nil { + fmt.Println(err) + } + fmt.Println(string(json)) // ["a","b","c"] +} +``` + ### Sort Sort is a general purpose sort function. From febc429423db72ef7baf54adbd6bbec4e383fb62 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Mon, 6 Mar 2017 05:23:07 +0100 Subject: [PATCH 12/12] - update documentation on serialization --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cdc1830..f9b415e 100644 --- a/README.md +++ b/README.md @@ -1304,13 +1304,13 @@ import ( func main() { list := arraylist.New() - list.Add("a", "b", "c") - json, err := list.ToJSON() + json := []byte(`["a","b"]`) + err := list.FromJSON(json) if err != nil { fmt.Println(err) } - fmt.Println(string(json)) // ["a","b","c"] + fmt.Println(list) // ArrayList ["a","b"] } ```