Skip to content

Commit

Permalink
JSON.ARRPOP added
Browse files Browse the repository at this point in the history
  • Loading branch information
Shivam010 committed Jan 2, 2019
1 parent 151cc9f commit 6ad557a
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 3 deletions.
18 changes: 17 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
debug.test
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# IDE Preferences
.idea/
.vscode/
.vs/
86 changes: 86 additions & 0 deletions examples/json_array.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package main

import (
"encoding/json"
"flag"
"fmt"
"github.com/gomodule/redigo/redis"
"github.com/nitishm/go-rejson"
"log"
)

func main() {
var addr = flag.String("Server", "localhost:6379", "Redis server address")

flag.Parse()

conn, err := redis.Dial("tcp", *addr)
if err != nil {
log.Fatalf("Failed to connect to redis-server @ %s", *addr)
}
defer func() {
conn.Do("FLUSHALL")
conn.Close()
}()

ArrIn := []string{"one", "two", "three", "four", "five"}
res, err := rejson.JSONSet(conn, "arr", ".", ArrIn, false, false)
if err != nil {
log.Fatalf("Failed to JSONSet")
return
}
fmt.Println("arr:", res)

res, err = rejson.JSONGet(conn, "arr", ".")
if err != nil {
log.Fatalf("Failed to JSONGet")
return
}
var ArrOut []string
err = json.Unmarshal(res.([]byte), &ArrOut)
if err != nil {
log.Fatalf("Failed to JSON Unmarshal")
return
}
fmt.Println("arr before pop:", ArrOut)

res, err = rejson.JSONArrLen(conn, "arr", ".")
if err != nil {
log.Fatalf("Failed to JSONArrLen")
return
}
fmt.Println("Length:", res)

res, err = rejson.JSONArrPop(conn, "arr", ".", rejson.PopArrLast)
if err != nil {
log.Fatalf("Failed to JSONArrLen")
return
}
var ele string
err = json.Unmarshal(res.([]byte), &ele)
if err != nil {
log.Fatalf("Failed to JSON Unmarshal")
return
}
fmt.Println("Deleted element:", ele)

res, err = rejson.JSONGet(conn, "arr", ".")
if err != nil {
log.Fatalf("Failed to JSONGet")
return
}
err = json.Unmarshal(res.([]byte), &ArrOut)
if err != nil {
log.Fatalf("Failed to JSON Unmarshal")
return
}
fmt.Println("arr after pop:", ArrOut)

res, err = rejson.JSONArrLen(conn, "arr", ".")
if err != nil {
log.Fatalf("Failed to JSONArrLen")
return
}
fmt.Println("Length:", res)

}
28 changes: 26 additions & 2 deletions rejson.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import (
"github.com/gomodule/redigo/redis"
)

// PopArrLast gives index of the last element for JSONArrPop
const PopArrLast = -1

// commandMux maps command name to a command function
var commandMux = map[string]func(argsIn ...interface{}) (argsOut []interface{}, err error){
"JSON.SET": commandJSONSet,
Expand All @@ -20,6 +23,7 @@ var commandMux = map[string]func(argsIn ...interface{}) (argsOut []interface{},
"JSON.STRLEN": commandJSONStrLen,
"JSON.ARRAPPEND": commandJSONArrAppend,
"JSON.ARRLEN": commandJSONArrLen,
"JSON.ARRPOP": commandJSONArrPop,
}

func commandJSONSet(argsIn ...interface{}) (argsOut []interface{}, err error) {
Expand Down Expand Up @@ -131,6 +135,18 @@ func commandJSONArrLen(argsIn ...interface{}) (argsOut []interface{}, err error)
return
}

func commandJSONArrPop(argsIn ...interface{}) (argsOut []interface{}, err error) {
key := argsIn[0]
path := argsIn[1]
index := argsIn[2]

argsOut = append(argsOut, key, path)
if index.(int) != PopArrLast {
argsOut = append(argsOut, index)
}
return
}

// CommandBuilder is used to build a command that can be used directly with redigo's conn.Do()
// This is especially useful if you do not need to conn.Do() and instead need to use the JSON.* commands in a
// MUTLI/EXEC scenario along with some other operations like GET/SET/HGET/HSET/...
Expand Down Expand Up @@ -245,9 +261,17 @@ func JSONArrAppend(conn redis.Conn, key string, path string, values ...interface
return conn.Do(name, args...)
}

// // JSONArrLen returns the length of the json array at path
// // JSON.ARRLEN <key> [path]
// JSONArrLen returns the length of the json array at path
// JSON.ARRLEN <key> [path]
func JSONArrLen(conn redis.Conn, key string, path string) (res interface{}, err error) {
name, args, _ := CommandBuilder("JSON.ARRLEN", key, path)
return conn.Do(name, args...)
}

// JSONArrPop removes and returns element from the index in the array
// to pop last element use rejson.PopArrLast
// JSON.ARRPOP <key> [path [index]]
func JSONArrPop(conn redis.Conn, key, path string, index int) (res interface{}, err error) {
name, args, _ := CommandBuilder("JSON.ARRPOP", key, path, index)
return conn.Do(name, args...)
}
96 changes: 96 additions & 0 deletions rejson_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rejson

import (
"encoding/json"
"reflect"
"testing"

Expand Down Expand Up @@ -1075,3 +1076,98 @@ func TestJSONArrLen(t *testing.T) {
})
}
}

func TestJSONArrPop(t *testing.T) {
conn, err := redis.Dial("tcp", ":6379")
if err != nil {
t.Fatal("Could not connect to redis.")
return
}
defer func() {
conn.Do("FLUSHALL")
conn.Close()
}()

values := make([]interface{}, 0)
valuesStr := []string{"one", "two", "three", "four"}
for _, value := range valuesStr {
values = append(values, value)
}
_, err = JSONSet(conn, "karr", ".", values, false, false)
if err != nil {
return
}

_, err = JSONSet(conn, "kstr", ".", "SimpleString", false, false)
if err != nil {
return
}

type args struct {
conn redis.Conn
key string
path string
index int
values []interface{}
}
tests := []struct {
name string
args args
wantRes interface{}
wantErr bool
}{
{
name: "SimpleArrayLastPop",
args: args{
conn: conn,
key: "karr",
path: ".",
index: PopArrLast,
},
wantRes: string("four"),
wantErr: false,
},
{
name: "SimpleArray2ndElementPop",
args: args{
conn: conn,
key: "karr",
path: ".",
index: 1,
},
wantRes: "two",
wantErr: false,
},
{
name: "SimpleStringNotOK",
args: args{
conn: conn,
key: "kstr",
path: ".",
index: PopArrLast,
},
wantRes: redis.Error("ERR wrong type of path value - expected array but found string"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
res, err := JSONArrPop(tt.args.conn, tt.args.key, tt.args.path, tt.args.index)
if (err != nil) != tt.wantErr {
t.Errorf("JSONArrPop() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
var gotRes interface{}
err = json.Unmarshal(res.([]byte), &gotRes)
if err != nil {
t.Errorf("JSONArrPop(): Failed to JSON Unmarshal")
return
}
if !reflect.DeepEqual(gotRes, tt.wantRes) {
t.Errorf("JSONArrPop() = %v, want %v", gotRes, tt.wantRes)
}
}
})
}
}

0 comments on commit 6ad557a

Please sign in to comment.