Repository: diegoholiveira/jsonlogic (go)

Issue:
Error if var is missing from data
Hello,

I seem to hit a case where the library is returning an error when a property, that is in the "logic" but not in the "data". Below is an example program to reproduce the issue.

```go
package main

import (
	"bytes"
	"fmt"
	"os"
	"strings"

	"github.com/diegoholiveira/jsonlogic"
)

func main() {
	logic := strings.NewReader(`{"logic":{"and":[{"!":{"var":"var_not_in_data"}}]}}`)
	data := strings.NewReader(`{"some_key": "value"}`)

	var result bytes.Buffer
	err := jsonlogic.Apply(logic, data, &result)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	fmt.Println(result.String())
}
```

And here's the output:

```
interface conversion: interface {} is nil, not []interface {}

Process finished with exit code 1
```

If I add the `var_not_in_data` to the `data` object it evaluates the expression correctly.

Edit Note: It used to panic with version 2, it just returns the error now with v3

Pull request:
The operation if there's a nil values
closes #37 

Patch:
diff --git a/.travis.yml b/.travis.yml
index a2afee0..baef9eb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,7 @@ sudo: false
 go:
   - "1.13"
   - "1.14"
+  - "1.15"
 script:
   - go test -coverprofile=coverage.txt -covermode=count
 after_success:
diff --git a/jsonlogic.go b/jsonlogic.go
index 7688af6..a1db1bd 100644
--- a/jsonlogic.go
+++ b/jsonlogic.go
@@ -533,6 +533,7 @@ func ApplyRaw(rule, data json.RawMessage) (json.RawMessage, error) {
 func ApplyInterface(rule, data interface{}) (output interface{}, err error) {
 	defer func() {
 		if e := recover(); e != nil {
+			// fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
 			err = e.(error)
 		}
 	}()
diff --git a/operation.go b/operation.go
index c5a0830..99ff855 100644
--- a/operation.go
+++ b/operation.go
@@ -45,12 +45,32 @@ func operation(operator string, values, data interface{}) interface{} {
 		return min(values)
 	}
 
+	if values == nil {
+		return nil
+	}
+
 	parsed := values.([]interface{})
 
+	if operator == "and" {
+		return _and(parsed)
+	}
+
+	if operator == "or" {
+		return _or(parsed)
+	}
+
 	if len(parsed) == 1 {
 		return unary(operator, parsed[0])
 	}
 
+	if operator == "?:" {
+		if parsed[0].(bool) {
+			return parsed[1]
+		}
+
+		return parsed[2]
+	}
+
 	if operator == "+" {
 		return sum(values)
 	}
@@ -67,22 +87,6 @@ func operation(operator string, values, data interface{}) interface{} {
 		return div(values)
 	}
 
-	if operator == "and" {
-		return _and(parsed)
-	}
-
-	if operator == "or" {
-		return _or(parsed)
-	}
-
-	if operator == "?:" {
-		if parsed[0].(bool) {
-			return parsed[1]
-		}
-
-		return parsed[2]
-	}
-
 	if operator == "in" {
 		return _in(parsed[0], parsed[1])
 	}


Test patch:
diff --git a/jsonlogic_test.go b/jsonlogic_test.go
index d94f23f..f0fea44 100644
--- a/jsonlogic_test.go
+++ b/jsonlogic_test.go
@@ -529,3 +529,13 @@ func TestBetweenIsBigger(t *testing.T) {
 
 	assert.JSONEq(t, expected, result.String())
 }
+
+func TestUnaryOperation(t *testing.T) {
+	logic := strings.NewReader(`{"and":[{"!":{"var":"var_not_in_data"}}]}`)
+	data := strings.NewReader(`{"some_key": "value"}`)
+
+	var result bytes.Buffer
+	assert.Nil(t, Apply(logic, data, &result))
+
+	assert.JSONEq(t, `true`, result.String())
+}