Skip to content

Commit

Permalink
feat: add function to get jsonlogic with solved vars (replaced by val…
Browse files Browse the repository at this point in the history
…ues) (#66)

* feat: implement method to get json logic with vars replaced by values

* feat: change a comment

* feat: update package name

* feat: update readme

* feat: method to get json logic with solved vars
  • Loading branch information
FlorianRuen authored Aug 2, 2023
1 parent 1a4645b commit bbdc99d
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

.idea/
.idea/
.vscode/
22 changes: 22 additions & 0 deletions jsonlogic.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,28 @@ func Apply(rule, data io.Reader, result io.Writer) error {
return json.NewEncoder(result).Encode(output)
}

func GetJsonLogicWithSolvedVars(rule, data json.RawMessage) ([]byte, error) {
if data == nil {
data = json.RawMessage("{}")
}

// parse rule and data from json.RawMessage to interface
var _rule interface{}
var _data interface{}

err := json.Unmarshal(rule, &_rule)
if err != nil {
return nil, err
}

err = json.Unmarshal(data, &_data)
if err != nil {
return nil, err
}

return solveVarsBackToJsonLogic(_rule, _data)
}

func ApplyRaw(rule, data json.RawMessage) (json.RawMessage, error) {
if data == nil {
data = json.RawMessage("{}")
Expand Down
52 changes: 52 additions & 0 deletions jsonlogic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,3 +740,55 @@ func TestIssue58_example(t *testing.T) {
expected := `{"foo":"is_bar","path":"foo_is_bar"}`
assert.JSONEq(t, expected, result.String())
}

func TestJsonLogicWithSolvedVars(t *testing.T) {
rule := json.RawMessage(`{
"or":[
{
"and":[
{"==": [{ "var":"is_foo" }, true ]},
{"==": [{ "var":"is_bar" }, true ]},
{">=": [{ "var":"foo" }, 17179869184 ]},
{"==": [{ "var":"bar" }, 0 ]}
]
},
{
"and":[
{"==": [{ "var":"is_bar" }, true ]},
{"==": [{ "var":"is_foo" }, false ]},
{"==": [{ "var":"foo" }, 34359738368 ]},
{"==": [{ "var":"bar" }, 0 ]}
]
}]
}`)

data := json.RawMessage(`{"foo": 34359738368, "bar": 10, "is_foo": false, "is_bar": true}`)

output, err := GetJsonLogicWithSolvedVars(rule, data)

if err != nil {
t.Fatal(err)
}

expected := `{
"or":[
{
"and":[
{ "==":[ false, true ] },
{ "==":[ true, true ] },
{ ">=":[ 34359738368, 17179869184 ] },
{ "==":[ 10, 0 ] }
]
},
{
"and":[
{ "==":[ true, true ] },
{ "==":[ false, false ] },
{ "==":[ 34359738368, 34359738368 ] },
{ "==":[ 10, 0 ] }
]
}]
}`

assert.JSONEq(t, expected, string(output))
}
60 changes: 60 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,66 @@ func main() {
}
```

If you want to get the json logic used, with the variables replaced by their values :

```go
package main

import (
"fmt"
"encoding/json"

"github.com/diegoholiveira/jsonlogic/v3"
)

func main() {
logic := json.RawMessage(`{ "==":[{ "var":"foo" }, true] }`)
data := json.RawMessage(`{"foo": "false"}`)

result, err := jsonlogic.GetJsonLogicWithSolvedVars(logic, data)

if err != nil {
fmt.Println(err)
}

fmt.Println(string(result)) // will output { "==":[false, true] }
}

```

# License

This project is licensed under the MIT License - see the LICENSE file for details



For example, if you specify the folowing rules model :


```json
{
"and":[
{ "==":[{ "var":"VariableA" }, true] },
{ "==":[{ "var":"VariableB" }, true] },
{ ">=":[{ "var":"VariableC" }, 17179869184] },
{ "==":[{ "var":"VariableD" }, "0"] },
{ "<":[{ "var":"VariableE" }, 20] }
]
}

```

You will get as output, the folowing response (using a specific data, all variables will be replaced with matching values) :

```json
{
"and":[
{ "==":[false, true] },
{ "==":[true, true] },
{ ">=":[34359738368, 17179869184] },
{ "==":[12, "0"] },
{ "<":[14, 20] }
]
}

```
27 changes: 27 additions & 0 deletions vars.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package jsonlogic

import (
"encoding/json"
"strconv"
"strings"
)

Expand Down Expand Up @@ -105,3 +107,28 @@ func getVar(value, data interface{}) interface{} {

return _value
}

func solveVarsBackToJsonLogic(rule, data interface{}) (json.RawMessage, error) {
ruleMap := rule.(map[string]interface{})
result := make(map[string]interface{})

for operator, values := range ruleMap {
result[operator] = solveVars(values, data)
}

resultJson, err := json.Marshal(result)

if err != nil {
return nil, err
}

// we need to use Unquote due to unicode characters (example \u003e= need to be >=)
// used for prettier json.RawMessage
resultEscaped, err := strconv.Unquote(strings.Replace(strconv.Quote(string(resultJson)), `\\u`, `\u`, -1))

if err != nil {
return nil, err
}

return []byte(resultEscaped), nil
}

0 comments on commit bbdc99d

Please sign in to comment.