Built-in options for converting arbitrary Prolog term to JSON

I’m trying to convert an arbitrary Prolog term (which could literally be any legal Prolog term) to a JSON string. My personal ideal format would have a Prolog term be represented as a JSON dict with one key/value: the key is the name of the predicate and the value is a list containing args. Lists just become a JSON list. Like this:

Prolog JSON
a {“a”:[]}
a(b) {“a”:[{“b”:[]}]}
a[b] {“a”:[[{“b”:[]}]]}

But I have some flexibility on other transformations if need be.

For some reason I’m really struggling to understand how this works in the system. It appears as though:

  • library(http/json) is for conversion between a JSON String and a canonical Prolog term structure (but no ability to deal with arbitrary Prolog terms)
  • library(library(http/json_convert) is for creating mappings between your application specific Prolog terms and your own, custom, JSON expression of them. It appears daunting to define enough to do arbitrary Prolog terms.
  • library(library(term_to_json) seems to map arbitrary Prolog terms to a canonical JSON format that is different than the one library(http/json) uses?

Do I have this right? Are there other options in the system (beyond term_to_json/2) that can convert arbitrary Prolog terms to a JSON string somehow?

I’m just trying to see what options are available before I go write a bunch of custom code…

I think I answered my own question here: I was wrong above: term_to_json seems to be using the same canonical form that library(http/json) uses, since I can do this:

    term_to_json(Term, Json),
    json_write(Stream, Json)

The format it outputs is an easy transform to the one I need above. Wonderful!

I think you need to encode position as well, since dict doesn’t retain position information, whereas arguments are positional.

That is a great point. I hadn’t yet worked through converting back from JSON to prolog and I just noticed there is not a json_to_term predicate, possibly for this very reason. Dang.

It looks like library(http/json_convert) handles this by forcing you to write down all the “types” you use and what their arguments are. Then, it writes the “type” into the json and presumably doesn’t allow the arguments of a term to have duplicate names.

Hmm. Is there really not a built in library that does 2 way conversion between prolog and json without requiring the developer to declare all their types like library(http/json_convert)?

Actually, I take that back. The term_to_json/2 predicate does encode position of arguments because it represents the arguments in a json list, which preserves order.

Still looking for the reverse predicate though: json_to_term/2…

Good point.

I think dict doesn’t carry position information, whereas json does … and i got these two confused

Is json_to_prolog/2 what you’re looking for? (With json_object/1)
Also look at the tag option in json_read_dict/3

My goal is to find symmetric predicates which convert arbitrary prolog terms into a some json format, and back again. Such that:

?- term_to_json:term_to_json(a(b), Json).
Json = json{args:[b],functor:a}.

% This is the one I can't find
?- json_to_term(json{args:[b],functor:a}, Term).
Term = a(b)

Unless I’m missing something, json_to_prolog/2 requires you to declare all the predicates that are described in the json using json_object/1. I’m looking for a predicate which will take a canonical json format (like that created by term_to_json/2) and convert it into whatever Prolog terms the format describes, without having to declare them up front.

I belive json_read_dict/3 does the same thing that atom_json_term/2 does: convert a json string into a set of Prolog Json terms, not an actual “native” Prolog term:

?- json:atom_json_term('{"args":["b"],"functor":"a"}', Term, []).
Term = json([args=[b],functor=a]).