Search code examples
dictionaryprologswi-prolog

using dictionaries in swi-prolog


I'm working on a simple web service in Prolog and wanted to respond to my users with data formatted as JSON. A nice facility is reply_json_dict/1 which takes a dictionary and converts it in a HTTP response with well formatted JSON body.

My trouble is that building the response dictionary itself seems a little cumbersome. For example, when I return some data, I have data id but may/may not have data properties (possibly an unbound variable). At the moment I do the following:

OutDict0 = _{ id : DataId },
( nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0 ),
reply_json_dict(OutDict1)

Which works fine, so output is { "id" : "III" } or { "id" : "III", "attributes" : "AAA" } depending whether or not Props is bound, but... I'm looking for an easier approach. Primarily because if I need to add more optional key/value pairs, I end up with multiple implications like:

OutDict0 = _{ id : DataId },
( nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0 ),
( nonvar(Time) -> OutDict2 = OutDict1.put(_{ time : Time }) ; OutDict2 = OutDict1 ),
( nonvar(UserName) -> OutDict3 = OutDict2.put(_{ userName : UserName }) ; OutDict3 = OutDict2 ),
reply_json_dict(OutDict3)

And that seems just wrong. Is there a simpler way?

Cheers, Jacek


Solution

  • Many thanks mat and Boris for suggestions! I ended up with a combination of your ideas:

    dict_filter_vars(DictIn, DictOut) :-
        findall(Key=Value, (get_dict(Key, DictIn, Value), nonvar(Value)), Pairs),
        dict_create(DictOut, _, Pairs).
    

    Which then I can use as simple as that:

    DictWithVars = _{ id : DataId, attributes : Props, time : Time, userName : UserName },
    dict_filter_vars(DictWithVars, DictOut),
    reply_json_dict(DictOut)