Skip to content

Commit

Permalink
feat(logic): convert basic json object into prolog
Browse files Browse the repository at this point in the history
bdeneux committed Apr 26, 2023

Verified

This commit was signed with the committer’s verified signature.
bdeneux Benjamin DENEUX
1 parent e43010d commit 310459a
Showing 2 changed files with 58 additions and 3 deletions.
16 changes: 16 additions & 0 deletions x/logic/predicate/json.go
Original file line number Diff line number Diff line change
@@ -3,9 +3,11 @@ package predicate
import (
"encoding/json"
"fmt"
"sort"

"github.com/ichiban/prolog/engine"
"github.com/okp4/okp4d/x/logic/util"
"github.com/samber/lo"
)

// AtomJSON is a term which represents a json as a compound term `json([Pair])`.
@@ -46,6 +48,20 @@ func jsonToTerms(value any) (engine.Term, error) {
switch v := value.(type) {
case string:
return util.StringToTerm(v), nil
case map[string]any:
keys := lo.Keys(v)
sort.Strings(keys)

attributes := make([]engine.Term, 0, len(v))
for _, key := range keys {
attributeValue, err := jsonToTerms(v[key])
if err != nil {
return nil, err
}
attributes = append(attributes, AtomPair.Apply(engine.NewAtom(key), attributeValue))
}

return AtomJSON.Apply(engine.List(attributes...)), nil
default:
return nil, fmt.Errorf("could not convert %s (%T) to a prolog term", v, v)
}
45 changes: 42 additions & 3 deletions x/logic/predicate/json_test.go
Original file line number Diff line number Diff line change
@@ -19,23 +19,62 @@ import (
func TestJsonProlog(t *testing.T) {
Convey("Given a test cases", t, func() {
cases := []struct {
description string
program string
query string
wantResult []types.TermResults
wantError error
wantSuccess bool
}{
// ** JSON -> Prolog **
// String
{
query: `json_prolog('"foo"', Term).`,
description: "convert direct string (valid json) into prolog",
query: `json_prolog('"foo"', Term).`,
wantResult: []types.TermResults{{
"Term": "foo",
}},
wantSuccess: true,
},
{
query: `json_prolog('{"foo": "bar"}', Term).`,
description: "convert direct string with space (valid json) into prolog",
query: `json_prolog('"a string with space"', Term).`,
wantResult: []types.TermResults{{
"Term": "json([-(foo, 'bar')])",
"Term": "'a string with space'",
}},
wantSuccess: true,
},
// ** JSON -> Prolog **
// Object
{
description: "convert json object into prolog",
query: `json_prolog('{"foo": "bar"}', Term).`,
wantResult: []types.TermResults{{
"Term": "json([foo-bar])",
}},
wantSuccess: true,
},
{
description: "convert json object with multiple attribute into prolog",
query: `json_prolog('{"foo": "bar", "foobar": "bar foo"}', Term).`,
wantResult: []types.TermResults{{
"Term": "json([foo-bar,foobar-'bar foo'])",
}},
wantSuccess: true,
},
{
description: "convert json object with attribute with a space into prolog",
query: `json_prolog('{"string with space": "bar"}', Term).`,
wantResult: []types.TermResults{{
"Term": "json(['string with space'-bar])",
}},
wantSuccess: true,
},
{
description: "ensure determinism on object attribute key sorted alphabetically",
query: `json_prolog('{"b": "a", "a": "b"}', Term).`,
wantResult: []types.TermResults{{
"Term": "json([a-b,b-a])",
}},
wantSuccess: true,
},

0 comments on commit 310459a

Please sign in to comment.