Merge pull request #53 from emirpasic/json

JSON serialization (marshaling) / deserialization (unmarshaling)
pull/55/head v1.9.0
Emir Pasic 7 years ago committed by GitHub
commit f6c17b5248

@ -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 redblack [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. <sub><sup>[Wikipedia](http://en.wikipedia.org/wiki/Red%E2%80%93black_tree)</sup></sub>
Implements [Tree](#trees) and [ReverseIteratorWithKey](#reverseiteratorwithkey) interfaces.
Implements [Tree](#trees), [ReverseIteratorWithKey](#reverseiteratorwithkey), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.
<p align="center"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Red-black_tree_example.svg/500px-Red-black_tree_example.svg.png" width="400px" height="200px" /></p>
@ -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 redblack 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 redblack trees because they are more strictly balanced. <sub><sup>[Wikipedia](https://en.wikipedia.org/wiki/AVL_tree)</sup></sub>
Implements [Tree](#trees) and [ReverseIteratorWithKey](#reverseiteratorwithkey) interfaces.
Implements [Tree](#trees), [ReverseIteratorWithKey](#reverseiteratorwithkey), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.
<p align="center"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/AVL-tree-wBalance_K.svg/262px-AVL-tree-wBalance_K.svg.png" width="300px" height="180px" /><br/><sub>AVL tree with balance factors (green)</sub></p>
@ -664,7 +667,7 @@ According to Knuth's definition, a B-tree of order m is a tree which satisfies t
Each internal nodes 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.<sub><sup>[Wikipedia](http://en.wikipedia.org/wiki/Red%E2%80%93black_tree)</sub></sup>
Implements [Tree](#trees) and [ReverseIteratorWithKey](#reverseiteratorwithkey) interfaces.
Implements [Tree](#trees), [ReverseIteratorWithKey](#reverseiteratorwithkey), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.
<p align="center"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/6/65/B-tree.svg/831px-B-tree.svg.png" width="400px" height="111px" /></p>
@ -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. <sub><sup>[Wikipedia](http://en.wikipedia.org/wiki/Binary_heap)</sub></sup>
Implements [Tree](#trees) and [ReverseIteratorWithIndex](#reverseiteratorwithindex) interfaces.
Implements [Tree](#trees), [ReverseIteratorWithIndex](#reverseiteratorwithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.
<p align="center"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Max-Heap.svg/501px-Max-Heap.svg.png" width="300px" height="200px" /></p>
@ -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()
json := []byte(`["a","b"]`)
err := list.FromJSON(json)
if err != nil {
fmt.Println(err)
}
fmt.Println(list) // ArrayList ["a","b"]
}
```
### Sort
Sort is a general purpose sort function.

@ -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"

@ -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
}

@ -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"}
}

@ -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++ {

@ -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
}

@ -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++ {

@ -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
}

@ -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
}

@ -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++ {

@ -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

@ -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
}

@ -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

@ -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
}

@ -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
}

@ -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++ {

@ -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)
}

@ -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++ {

@ -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++ {

@ -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
}

@ -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
}

@ -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++ {

@ -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++ {

@ -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)
}

@ -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++ {

@ -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)
}

@ -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++ {

@ -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
}

@ -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++ {

@ -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)
}

@ -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++ {

@ -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
}

@ -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++ {

@ -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
}

@ -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)
}
}

@ -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)
}
}
Loading…
Cancel
Save