Skip to content

Commit

Permalink
feat(logic): json_prolog/2 handle list term to json array
Browse files Browse the repository at this point in the history
  • Loading branch information
bdeneux committed Apr 28, 2023
1 parent 4bb3f9a commit 4e2b8b6
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 9 deletions.
36 changes: 27 additions & 9 deletions x/logic/predicate/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,39 @@ func termsToJson(term engine.Term, env *engine.Env) ([]byte, error) {
switch t := term.(type) {
case engine.Atom:
return json.Marshal(t.String())
case engine.Integer:
return json.Marshal(t)
case engine.Compound:
terms, err := ExtractJsonTerm(t, env)
if err != nil {
return nil, err
}
if t.Arity() == 2 && t.Functor().String() == "." {
// It's engine.List
iter := engine.ListIterator{List: t, Env: env}

attributes := make(map[string]json.RawMessage, len(terms))
for key, term := range terms {
raw, err := termsToJson(env.Resolve(term), env)
elements := make([]json.RawMessage, 0)
for iter.Next() {
element, err := termsToJson(env.Resolve(iter.Current()), env)
if err != nil {
return nil, err
}
elements = append(elements, element)
}
return json.Marshal(elements)
} else {
// It's a json atom
terms, err := ExtractJsonTerm(t, env)
if err != nil {
return nil, err
}
attributes[key] = raw

attributes := make(map[string]json.RawMessage, len(terms))
for key, term := range terms {
raw, err := termsToJson(env.Resolve(term), env)
if err != nil {
return nil, err
}
attributes[key] = raw
}
return json.Marshal(attributes)
}
return json.Marshal(attributes)
default:
return nil, fmt.Errorf("could not convert %s {%T} to json", t, t)
}
Expand Down
34 changes: 34 additions & 0 deletions x/logic/predicate/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,40 @@ func TestJsonProlog(t *testing.T) {
wantSuccess: false,
wantError: fmt.Errorf("json_prolog/2: invalid functor foo. Expected json"),
},
// ** Prolog -> JSON **
// Number
{
description: "convert json number from prolog",
query: `json_prolog(Json, 10).`,
wantResult: []types.TermResults{{
"Json": "'10'",
}},
wantSuccess: true,
},
{
description: "decimal number not compatible yet",
query: `json_prolog(Json, 10.4).`,
wantSuccess: false,
wantError: fmt.Errorf("json_prolog/2: could not convert %%!s(engine.Float=10.4) {engine.Float} to json"),
},
// ** Prolog -> Json **
// Array
{
description: "convert json array from prolog",
query: `json_prolog(Json, [foo,bar]).`,
wantResult: []types.TermResults{{
"Json": "'[\"foo\",\"bar\"]'",
}},
wantSuccess: true,
},
{
description: "convert json string array from prolog",
query: `json_prolog(Json, ['string with space',bar]).`,
wantResult: []types.TermResults{{
"Json": "'[\"string with space\",\"bar\"]'",
}},
wantSuccess: true,
},
}
for nc, tc := range cases {
Convey(fmt.Sprintf("Given the query #%d: %s", nc, tc.query), func() {
Expand Down

0 comments on commit 4e2b8b6

Please sign in to comment.