Json

json(
                  ["id" = Lid, "rows" = json([ "0" = json(["product_id" = "3", "price" = "170", "quantity" = "1"])])]
              )

I send this json with a post request, I get it in the http logs

completed(1, 0.077131914, 380, 500, error("Type error: `json_term' expected, found `\"id\"='995397'' (a compound)")). 

how to generate json correctly?

Keys are atoms, not strings. For new code, better use the “dict” exchange.

how should it look for me ?

Examples: json( at SWI-Prolog -- Manual

it’s still not clear what’s wrong with this json

    http_post([ protocol(https),
                host('vod.bitrix24.ru'),
                port(443),
                path('/rest/1/benwqt55sthigqm/')
              ],
              json(
                  [id = Lid, rows = json([(product_id = 3, price = 170, quantity = 1)])]
              ),
              Reply,
              []),
completed(46, 0.003182232000000007, 378, 500, error("Type error: `json_term' expected, found `id=\"996331\"' (a compound)")).

I think you need json/1 term twice, as the outer one tells the data is json. In that you need a valid json term, so you get

json(json([id=...])).

oh it’s not obvious

Note that the JSON return does not need to be an object. For example, json("Hello World") is fine to reply just a string.

tell me what’s wrong with the url?

error("url `'https://vod.bitrix24.ru/rest/1/benwqt55sthigqm'' does not exist (status(4
00,Bad Request))")).

Is that an extra wrapping of single quotes?

I didn’t pack anything

Trailing slash missing, perhaps.

at the end ? i tried it, the result is the same

Oh, it’s a 400 error - check your JSON. The does not exist is misleading.

how to see what json is being sent?

requestcatcher.com is useful, to see your raw request in all its detail.

1 Like
completed(142, 0.0030008180000002938, 404, 500, error("url `'https://vodanahodka.requestcatcher.com/test'' does not exist (status(400,Bad Reque
st))")).

still just as bad

                host('vodanahodka.requestcatcher.com'),
                path('/test')
              ],
              json(
                  json([id = Lid, rows = json([product_id = 3, price = 170, quantity = 1])])
              ),
              Reply,
              []),

I couldn’t get http_post to work with json(...) terms. Instead, I converted the json term to an atom. For example,

   atom_json_term(D,json([model=Model,prompt=Prompt|Options]),[]),
   Data = atom(application/json,D),
   http_post('https://api.openai.com/v1/completions',Data,ReturnData,
            [authorization(bearer(Key)),application/json]),

(the intermediate step of Data = ... isn’t strictly necessary, but I’ve used it for clarity.

Without complete code it is always hard to tell. Here is a small stand alone program:

:- use_module(library(http/http_server)).
:- use_module(library(http/http_client)).
:- use_module(library(pprint)).
:- use_module(library(debug)).

:- http_handler(root(test), test, []).

server(Port) :-
    http_server([port(Port)]).

test(Request) :-
    assertion(memberchk(method(post), Request)),
    http_read_data(Request, Data, []),
    format('Content-type: text/plain~n~n'),
    print_term(Data, [output(current_output)]).

client(Port, Data, Return) :-
    format(string(URL), 'http://localhost:~d/test', [Port]),
    http_post(URL, Data, Return, []).

Load it, and then:

101 ?- server(4000).
% Started server at http://localhost:4000/
true.

102 ?- client(4000, json(json([a=1,b=2])), R).
R = 'json([a=1,b=2])'.

103 ?- client(4000, json(#{a:1, b:2}), R).
R = 'json([a=1,b=2])'.

Note the double json in the first example, where the outer says the data is JSON and the inner passes a JSON object. In the second example we use a dict for the JSON data.

I made a small demo of a browser client (written in Javascript) communicating with a server (written in Prolog) using JSON: GitHub - kamahen/swipl-server-js-client: Sample SWI-Prolog server with JavaScript client

(There are other demos, but I found that they were either missing some information or were using obsolete libraries. No doubt my demo will become obsolete in a few years also)

(TODO: add support for SSL - the “how-to” has been posted elsewhere in this discourse group but I haven’t updated my demo with it yet)