Pedro Gonçalves
Pedro Gonçalves

Reputation: 121

Prolog Json handle

server():- http_server(http_dispatch, [port(45000)]).

serverTest(Request):-http_read_json(Request, JSONIn),
  json_to_prolog(JSONIn, PrologIn), format(PrologIn) .

I have this Prolog program but I can't handle the PrologIn variable very well. I get this error:

Type error: `text' expected, found `json([id=3])'

I know that means I can't use format with PrologIn but how do I handle the information inside? Meaning, how do I extract the "id = 3" info ?

Edit:

This is the full program

(If I use more than enough modules, is because I'm doing other stuff with the program and didn't filtered to this specific case)

:- use_module(library(http/thread_httpd)). 
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_parameters)). 
:- use_module(library(http/http_ssl_plugin)).
:- use_module(library(http/http_open)).
:- use_module(library(http/http_client)).
:- use_module(library(http/http_json)).
:- use_module(library(http/json)).

:- http_handler('/test', serverTest, []).

The rest is the first two predicts before the edit

I test this by first going on the Prolog's console and typing "server().", this starts the server. Then I use Postman in the following way: Select POST, in the Headers the key is Content-Type and its value is application/json, then, in the Body, I select raw (JSON(application-json)) and write this in the text area:

{
  "id" : 3
}

This is how I test it, I want to be able to handle the id=3 information in the prolog predicate (serverTest).

Upvotes: 1

Views: 434

Answers (2)

user1812457
user1812457

Reputation:

You really need to show the full program, how you start the server, and how you query it. Otherwise, one can only guess.

Anyway, few problems with this: format(PrologIn).

First, as the program tells you, this is a term. And format does formatted output. At the very least, you would have to write:

format("~w", [PrologIn])

See the documentation on format/2, basically, if your term looks like this: json([id=3]), you should get json([id=3]) printed.

Now the next question: where would this print to? When you start a server with the HTTP package libraries, input and output are redirected so that you can read requests and write responses. There are many examples in the library documentation.

Then the next thing: how you get the 3 out of there. If you additionally load the http_json plugin module:

:- use_module(library(http/http_json)).

then you can directly use, as shown in the code example,

http_read_json_dict(Request, DictIn)

Now DictIn is a "dict" probably looking like this: _{id:3}. See the documentation on dicts.

You don't have to use dicts, just inspect the json term using normal pattern matching and list processing. Dicts are just easier (as in, less typing) for some use cases.

Edit

Here is a minimal example that works for me. This is the server code:

:- use_module(library(http/thread_httpd)). 
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_json)).

:- http_handler('/test', test, []).

server :-
    http_server(http_dispatch, [port(45000)]).

test(Request) :-
    http_read_json_dict(Request, JSON),
    format(user_error, "~w~n", [JSON.id]).

From the top level, after consulting the file, I run:

?- server.
% Started server at http://localhost:45000/
true.

At that point, I use curl from another command line like this:

$ curl -H "Content-Type: application/json" -d '{"id":3}' http://localhost:45000/test
curl: (52) Empty reply from server

and I get the 3 printed out on the Prolog toplevel where the server is running:

?- 3

This is of course not ideal, so I replace the last line in the server code with the following:

reply_json(_{foobar:JSON.id}).

and then on the Prolog toplevel, where the server is running, I use make/0:

?- make.
% Updating index for library .../lib/swipl-7.3.35/library/
% ... compiled 0.00 sec, 0 clauses
true.

Now, when I again use curl:

$ curl -H "Content-Type: application/json" -d '{"id":3}' http://localhost:45000/test
{"foobar":3}

This is all you need!

Upvotes: 4

imhotap
imhotap

Reputation: 2490

I don't know your Prolog web library, but I'm guessing http_read_json already binds its second argument to a Prolog term so the the call to json_to_prolog is unnecessary and incorrect.

Try

serverTest(Request) :- http_read_json(Request, JSONIn), format(JSOnIn).

If you want to isolate the id number from what you receive, this could be as simple as

serverTest(Request) :- http_read_json(Request, json([id=X])),
     % ... do something with X value here ... %

Upvotes: 0

Related Questions