Need advice on how to work easier with json

[delivery=json([state=json([id=1,name='Delivery']),comment='',files=[],coordinate=json([longitude=127.5599578,latitude=50.2588662])]),
                    point=json([id='1006901',address='123 123',
                                coordinate=json([longitude=127.519798,latitude=50.306539]),
                                courier=json([id=80730,name='Test 1']),
                                warehouse=json([id=51564,name='Street']),
                                routeDate='2023-11-13T00:00:00',
                                pointType='Order',
                                point=json([id='1006901',address='Street',
                                            coordinate=json([longitude=127.519798,latitude=50.306539]),
                                            orderId=3774544]),
                                arriveTime='2023-11-13T10:00:00']),distanceFromOrder=6020.0]

How can I get the courier id value?

courier=json([id=80730,name='Test 1']),

I’d use the dict JSON representation. Then you can simply use the . notation. Using this notation you’ll have to write a helper that allows easy access to (nested) keys.

I receive this structure in the web server handler. How can I convert to a dictionary?

Depends how. If you read it explicitly, there is json_read_dict/3. json_read/3 has options to control the data representation.

http_read_data(Request, Data, []),

That is handled by library(http/http_json), where we find

json_read_to(In, Data, Options) :-
    memberchk(json_object(dict), Options),
    !,
    json_read_dict(In, Data, Options).
json_read_to(In, Data, Options) :-
    json_read(In, Data, Options).

So, pass json_object(dict) to http_read_data/3 and you get a dict.

These are some utility functions that I use when working with JSON as data structures (i.e., not the dict representation).

json_key_has_value(J, K, V) :- J = json(Data), selectchk((K=V), Data, _).
key_in_json_has_value(K, J, V) :- json_key_has_value(J, K, V).
key_value_in_json(K, V, J) :- json_key_has_value(J, K, V).
key_in_json(K, J) :- json_key_has_value(J, K, _).
pair_in_json(K-V, J) :- json_key_has_value(J, K, V).
json_has_pair(J, K-V) :- json_key_has_value(J, K, V).


json_key_has_some_value(J, K, ListValues) :-
    member(V, ListValues),
    json_key_has_value(J, K, V), !.

key_having_some_value_in_json(K, ListValues, J) :- json_key_has_some_value(J, K, ListValues).

match_element_pairs(Element, []) :- Element =.. [json | _].
match_element_pairs(Element, [K-V|Pairs]) :-
    Patterns = [K-V|Pairs],
    maplist(json_has_pair(Element), Patterns).
match_pairs_element(Pairs, Element) :- match_element_pairs(Element, Pairs).

distinct_values(Key, DistinctValues, [J|Json]) :-
    include(key_in_json(Key), [J|Json], HasKey),
    maplist(key_in_json_has_value(Key), HasKey, Values),
    list_to_set(Values, DistinctValues).

The whole grammar of “JSON-key-value” helper predicates wouldn’t have to be completely spelled out if I had used lambdas (though I found that the names help with keeping my train-of-thought straight, sometimes).

I found these are good enough for some exploratory data analysis kind of activities. The JSON data I was working with was completely flat, so I didn’t write any predicates that deal with values that are themselves objects or arrays (I actually did the opposite because I needed to locate implied hierarchies).