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.

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)