Get value from JSON object in Prolog - json

I have two questions.
How can I access the values in a JSON data structure in Prolog?
How can I yield a list of solutions from a predicate as JSON?
My Code:
handle(Request) :-
format(user_output,"I'm here~n",[]),
http_read_json(Request, DictIn,[json_object(term)]),
%beat(DictIn.name,DictIn.move,X),
%get list of solution of beat in to JSON and keep it in DictOut
reply_json(DictOut).

I assume you are using SWI Prolog. Your code suggests that you want to convert JSON to SWI Prolog dicts. So you need to change
http_read_json(Request, DictIn, [json_object(term)])
to
http_read_json(Request, DictIn, [json_object(dict)]),
or you can just use http_read_json_dict/2. Note that Request must be a PUT or POST request or else these predicates will throw a domain_error(Type, Term).
You can print out DictIn to take a look at what fields you want to extract.
For the response use reply_json_dict/{1, 2}.

Related

How to marshal a predicate from JSON in Prolog?

In Python it is common to marshal objects from JSON. I am seeking similar functionality in Prolog, either swi-prolog or scryer.
For instance, if we have JSON stating
{'predicate':
{'mortal(X)', ':-', 'human(X)'}
}
I'm hoping to find something like load_predicates(j) and have that data immediately consulted. A version of json.dumps() and loads() would also be extremely useful.
EDIT: For clarity, this will allow interoperability with client applications which will be collecting rules from users. That application is probably not in Prolog, but something like React.js.
I agree with the commenters that it would be easier to convert the JSON data to a .pl file in the proper format first and then load that.
However, you can load the predicates from JSON directly, convert them to a representation that Prolog understands, and use assertz to add them to the knowledge base.
If indeed the data contains all the syntax needed for a predicate (as is the case in the example data in the question) then converting the representation is fairly simple as you just need to concatenate the elements of the list into a string and then create a term out of the string. Note that this assumption skips step 2 in the first comment by Guy Coder.
Note that the Prolog JSON library is rather strict in which format it accepts: only double quotes are valid as string delimiters, and lists with singleton values (i.e., not key-value pairs) need to use the notation [a,b,c] instead of {a,b,c}. So first the example data needs to be rewritten:
{"predicate":
["mortal(X)", ":-", "human(X)"]
}
Then you can load it in SWI-Prolog. Minimal working example:
:- use_module(library(http/json)).
% example fact for testing
human(aristotle).
load_predicate(J) :-
% open the file
open(J, read, JSONstream, []),
% parse the JSON data
json_read(JSONstream, json(L)),
% check for an occurrence of the predicate key with value L2
member(predicate=L2, L),
% concatenate the list into a string
atomics_to_string(L2, S),
% create a term from the string
term_string(T, S),
% add to knowledge base
assertz(T).
Example run:
?- consult('mwe.pl').
true.
?- load_predicate('example_predicate.json').
true.
?- mortal(X).
X = aristotle.
Detailed explanation:
The predicate json_read stores the data in the following form:
json([predicate=['mortal(X)', :-, 'human(X)']])
This is a list inside a json term with one element for each key-value pair. The element has the syntax key=value. In the call to json_read you can already strip the json() term and store the list directly in the variable L.
Then member/2 is used to search for the compound term predicate=L2. If you have more than one predicate in the JSON file then you should turn this into a foreach or in a recursive call to process all predicates in the list.
Since the list L2 already contains a syntactically well-formed Prolog predicate it can just be concatenated, turned into a term using term_string/2 and asserted. Note that in case the predicate is not yet in the required format, you can construct a predicate out of the various pieces using built-in predicate manipulation functionality, see https://www.swi-prolog.org/pldoc/doc_for?object=copy_predicate_clauses/2 for some pointers.

jMeter: JSON assertion

When I send a HTTP request I want a specific JSON response. I tried doing this, but with no luck.
This is what I have.
This is what I receive.
$. is not a valid JsonPath expression, if you want everything - you can go for "deep scan" and "wildcard" operators like:
$..*
be aware that JSON Path doesn't return attributes names so you will be able to assert only values so you might need to reconsider your pattern.
Looking into "what you have" I would recommend using Response Assertion instead.

Valid JSON Format?

I have this complex JSON Format. I don't know Whether is this valid json format or not because the key i am looking for is not in the first two dictionaries but is there in the third dictionary ? Is this valid json format ? If so , how to do parsing in this scenario ?
As am not allowed to ask new question . I edited my old question.
At the end of the first two if blocks, if you put a return statement, that will stop the program from going to execute the Alamofire block.

serialize and deserialize Clojure ::namespaced-keywords in JSON

I am trying to serialize some Clojure data structure into a persistent database, and I currently use Chesire for that purpose.
Let's say I have a map that contains namespaced keywords like the following :
{:cemerick.friend/identity {:current friend, :authentications {friend {:identity friend, :roles #{:clojure-cms.handler/user}}}}}
It gets serialized into JSON, like that :
{"cemerick.friend/identity":{"current":"friend","authentications":{"friend":{"identity":"friend","roles":["clojure-cms.handler/user"]}}}}
When reading it back and serializing (with keywordization (parse-string data true)), I get back the following :
{:cemerick.friend/identity {:current friend, :authentications {:friend {:identity friend, :roles [clojure-cms.handler/user]}}}}
How can I parse this JSON with and get the same data as the original ?
Note : this question gives some context to what I am trying to achieve.
Looking at the tests in Chesire, it's quite obvious that the optional keyword parameter to parse-string will affect all name attributes in a JSON object, value attributes like the namespaced keyword in your example are not affected. Actually, your problem is two-fold: the original set is also not converted back correctly.
For the set problem, what you could do is to write a custom decoder as described in the Chesire documentation.
For the original problem, there is probably no direct way other than to post-process the returned map, find the value to :roles and turn the value into a keyword, like so (untested):
(defn postprocess-json [authmap]
(update-in authmap [:authentications :friend :roles] keyword))

Use JSON.stringify but the data still have array, what does it mean?

I have a data which are object array. It contains object arrays in a tree structure. I use JSON.stringify(myArray) but the data still contain array because I see [] inside the converted data.
In my case, I want all the data to be converted into json object not array regarding I need to used the data on TreeTable of SAPUI5.
Maybe I misunderstand. Please help me clear.
This is the example of the data that I got from JSON.stringify.
[{"value":{"Id":"00145E5BB2641EE284F811A7907717A3",
"Text":"BI-RA Reporting, analysis, and dashboards",
"Parent":"00145E5BB2641EE284F811A79076F7A3","Type":"BMF"},
"children":[{"value":{"Id":"00145E5BB2641EE284F811A7907737A3",
"Text":"WebIntelligence_4.1","Parent":"00145E5BB2641EE284F811A7907717A3",
"Type":"TWB"},"children":[{"value":{"Id":"00145E5BB2641EE284F811A7907757A3",
"Text":"Functional Areas","Parent":"00145E5BB2641EE284F811A7907737A3","Type":"TWB"},
"children":[{"value":{"Id":"00145E5BB2641EE284F811A7907777A3",
"Text":"CHARTING","Parent":"00145E5BB2641EE284F811A7907757A3","Type":"TWB"},
"children":[{"value":{"Id":"001999E0B9081EE28AB706BE26631E93",
"Text":"Drill","Parent":"00145E5BB2641EE284F811A7907777A3","Type":"TWB"},
"children":[{"value":{"Id":"001999E0B9081EE28AB706BE26633E93",
"Text":"[AUTO][ACCEPT] Drill on charts DHTML","Parent":"001999E0B9081EE28AB706BE26631E93",
"Type":"TWB","Ref":"UT_WEBI_CHARTS_DRILL_HTML"}},{"value":{"Id":"001999E0B9081EE28AB706BE26635E93",
"Text":"[AUTO][ACCEPT] Drill on charts JAVA","Parent":"001999E0B9081EE28AB706BE26631E93",
"Type":"TWB","Ref":"UT_WEBI_CHARTS_DRILL_JAVA"}}]},...
The output that I want shouldn't be array of object but should be something like...
{{"value":{
"Id":"00145E5BB2641EE284F811A7907717A3",
"Text":"BI-RA Reporting, analysis, and dashboards",
"Parent":"00145E5BB2641EE284F811A79076F7A3","Type":"BMF"},
"children":{
{"value":{
"Id":"00145E5BB2641EE284F811A7907737A3",
"Text":"WebIntelligence_4.1",
"Parent":"00145E5BB2641EE284F811A7907717A3",
"Type":"TWB"},
"children":{
{"value":{
"Id":"00145E5BB2641EE284F811A7907757A3",
"Text":"Functional Areas",
"Parent":"00145E5BB2641EE284F811A7907737A3",
"Type":"TWB"},...
JSON.stringify merely converts JavaScript data structures to a JSON-formatted string for consumption by other parsers (including JSON.parse). If you want it to stringify to a different value, you must change the source data structures first.
However, it seems that this can't be represented as anything other than an array because you have duplicate keys (i.e. value appears more than once). That would not be valid for a JavaScript object or a JSON representation of such.
I think what you want is
JSON.stringify(data[0]);
or perhaps
JSON.stringify(data[0].value);
where data is the object you passed in the question