Repository: diegoholiveira/jsonlogic
Pull request #54 (2022-07-21 21:10:46)

Allow the reduce function work with string values
Added support string type for reduce operation. 

Reason:
I'm using reduce to check the difference between two arrays, ignoring some fields. And it works on jsonlogic.com playground, but with the release v3.2.3 I got `The type "string" is not supported` err.

Sample: https://go.dev/play/p/_JJnqY-oh0n

data: `{"old":{"cars":[{"brand":"FORD","model":"RANGER","quantity":4},{"brand":"VW","model":"GOLF","quantity":2}]},"new":{"cars":[{"brand":"FORD","model":"RANGER","quantity":7},{"brand":"VW","model":"GOLF","quantity":8}]}}`
rule: `{"!=":[{"reduce":[{"var":"old.cars"},{"cat":[{"var":"current.brand"},{"var":"current.model"},"|",{"var":"accumulator"}]},""]},{"reduce":[{"var":"new.cars"},{"cat":[{"var":"current.brand"},{"var":"current.model"},"|",{"var":"accumulator"}]},""]}]}`

got err: `The type "string" is not supported`
expected err: nil
expected result: `false`


With this PR it works as expected :)

codecov[bot]: # [Codecov](https://codecov.io/gh/diegoholiveira/jsonlogic/pull/54?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Diego+Oliveira) Report
> Merging [#54](https://codecov.io/gh/diegoholiveira/jsonlogic/pull/54?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Diego+Oliveira) (d8c1265) into [master](https://codecov.io/gh/diegoholiveira/jsonlogic/commit/b3253f291d5ce72b456299c6055045744458d432?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Diego+Oliveira) (b3253f2) will **increase** coverage by `0.02%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##           master      #54      +/-   ##
==========================================
+ Coverage   95.97%   96.00%   +0.02%     
==========================================
  Files           9        9              
  Lines         920      925       +5     
==========================================
+ Hits          883      888       +5     
  Misses         25       25              
  Partials       12       12              
```



Patch:
diff --git a/arrays.go b/arrays.go
index 57eb4bc..e7c4f03 100644
--- a/arrays.go
+++ b/arrays.go
@@ -102,6 +102,9 @@ func reduce(values, data interface{}) interface{} {
 		} else if isNumber(parsed[2]) {
 			accumulator = toNumber(parsed[2])
 			valueType = "number"
+		} else if isString(parsed[2]) {
+			accumulator = toString(parsed[2])
+			valueType = "string"
 		} else {
 			panic(ErrReduceDataType{
 				dataType: fmt.Sprintf("%T", parsed[2]),
@@ -129,6 +132,8 @@ func reduce(values, data interface{}) interface{} {
 			context["accumulator"] = isTrue(v)
 		case "number":
 			context["accumulator"] = toNumber(v)
+		case "string":
+			context["accumulator"] = toString(v)
 		}
 	}
 


Test patch:
diff --git a/arrays_test.go b/arrays_test.go
index 7fa61e6..6441b40 100644
--- a/arrays_test.go
+++ b/arrays_test.go
@@ -88,3 +88,24 @@ func TestReduceBoolValues(t *testing.T) {
 
 	assert.Equal(t, expected, result)
 }
+
+func TestReduceStringValues(t *testing.T) {
+	var parsed interface{}
+
+	err := json.Unmarshal([]byte(`[
+		["a",null,"b"],
+		{"cat":[{"var":"current"}, {"var":"accumulator"}]},
+		""
+	]`), &parsed)
+	if err != nil {
+		panic(err)
+	}
+
+	result := reduce(parsed, nil)
+
+	var expected interface{}
+
+	json.Unmarshal([]byte(`"ba"`), &expected) // nolint:errcheck
+
+	assert.Equal(t, expected, result)
+}
diff --git a/jsonlogic_test.go b/jsonlogic_test.go
index 53f6d57..ed2adfb 100644
--- a/jsonlogic_test.go
+++ b/jsonlogic_test.go
@@ -593,7 +593,7 @@ func TestReduceFilterAndNotContains(t *testing.T) {
 }
 
 func TestReduceWithUnsupportedValue(t *testing.T) {
-	b := []byte(`{"reduce":[{"filter":[{"var":"data"},{"==":[{"var":""},""]}]},{"cat":[{"var":"current"},{"var":"accumulator"}]},"str"]}`)
+	b := []byte(`{"reduce":[{"filter":[{"var":"data"},{"==":[{"var":""},""]}]},{"cat":[{"var":"current"},{"var":"accumulator"}]},null]}`)
 
 	rule := map[string]interface{}{}
 	_ = json.Unmarshal(b, &rule)
@@ -602,7 +602,7 @@ func TestReduceWithUnsupportedValue(t *testing.T) {
 	}
 
 	_, err := ApplyInterface(rule, data)
-	assert.EqualError(t, err, "The type \"string\" is not supported")
+	assert.EqualError(t, err, "The type \"<nil>\" is not supported")
 }
 
 func TestAddOperator(t *testing.T) {