# Built-in options for converting arbitrary Prolog term to JSON

**URL:** <https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783>\
**Category:** Help!\
**Created:** [March 30, 2021, 10:12pm UTC](https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783 "2021-03-30T22:12:25Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [March 30, 2021, 10:12pm UTC](https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783/1 "2021-03-30T22:12:25Z")

</div>

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…

---

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [March 30, 2021, 11:43pm UTC](https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783/2 "2021-03-30T23:43:11Z")

</div>

> [@ericzinda](#):
>
> `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?

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:

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

```

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

---

<div class="post-metadata">

**Author:** ![grossdan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/grossdan/32/23_2.png) [@grossdan](https://swi-prolog.discourse.group/u/grossdan)\
**Post date:** [March 31, 2021, 5:30am UTC](https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783/3 "2021-03-31T05:30:49Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [March 31, 2021, 5:44pm UTC](https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783/4 "2021-03-31T17:44:40Z")

</div>

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)`?

---

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [March 31, 2021, 5:57pm UTC](https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783/5 "2021-03-31T17:57:02Z")

</div>

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…

---

<div class="post-metadata">

**Author:** ![grossdan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/grossdan/32/23_2.png) [@grossdan](https://swi-prolog.discourse.group/u/grossdan)\
**Post date:** [March 31, 2021, 6:10pm UTC](https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783/6 "2021-03-31T18:10:09Z")

</div>

Good point.

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

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [March 31, 2021, 6:38pm UTC](https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783/7 "2021-03-31T18:38:34Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [March 31, 2021, 7:38pm UTC](https://swi-prolog.discourse.group/t/built-in-options-for-converting-arbitrary-prolog-term-to-json/3783/8 "2021-03-31T19:38:02Z")

</div>

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

```prolog
?- 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:

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

```
