Returning values from AppleScript to Keyboard Maestro using JSON

I thought it possible that others might find this useful. Off and on I have toyed with a KeyboardMaestro macro that would save emails from Mail.app, and after looking at David’s recent addition to his KM Field Guide on this topic, I decided to resurrect my efforts. One thing that I have done a lot of in KM is execute AppleScripts and return data from the script to KM for further action.

I noted that David’s approach was to use a tell application "Keyboard Maestro Engine" code block in AS to set a variable in KM for later use, and of course you could use multiple such statements to return data.

My approach in the past has been to create some sort of complex string encoding of the data to be returned from AS to KM and have KM parse that data, but it turns out there is an somewhat easier way that others might find useful, using KM’s new JSON processing and parsing actions.

What I did was to use generate a JSON-like string in AS that is essentially in the format of a JSON dictionary, as follows:

Here is where I get the necessary information from the mail message referenced by “theMessage”:
-- Extract the needed information from the message
set _account to the name of the account of the mailbox of theMessage
set _subject to the subject of theMessage
set _sentDate to the date sent of theMessage
set _sender to the sender of theMessage

Here I build and return a string that looks like a JSON dictionary. Note that some careful attention to detail is needed to get all the quotation marks (") properly “quoted” with a backslash so they embed in the string properly. If I wind up doing this a lot I will have to create a subroutine to handle this that I can paste in as needed.

-- Build a "JSON" formatted return value
set retval to "{\"account\":\"" & _account & "\", \"subject\":\"" & _subject & "\", \"sentdate\":\"" & _sentDate & "\", \"sender\":\"" & _sender & "\"}"

return retval

`

I have the executed AS save the result to a variable called “Local_retval”.

What I then do is as part of the initialization of the script, set local variables “Local_account”, “Local_subject”, “Local_sentdate”, and “Local_sender” to blank text so they are part of the local execution environment of the macro and default to blank.

The following action then parses the JSON dictionary and put the values into each of the local variables:

After this action, Local_XXX will be set to the corresponding value from the JSON dictionary (eg {“XXX”: “foo”} would result in Local_XXX being set to “foo”.

I had not tried this before, but this provides a very convenient way to send complex data back from scripts to KM and easily parse it out. Since I do a lot of this, from both AS and Python, I think I will use this technique for a while.

Note that David’s approach is also clever and may well be more efficient, but I thought others might be interested in this idea.

4 Likes

Not to negate this at all, but would it be easier if your starting point was JXA, rather than AppleScript?

Most definitely. It would even be easier if I started with Python which has a good JSON module that I use all the time for parsing and generating JSON.

The problem is that there are just some things on MacOS that are easier to do in AppleScript than in anything else; I find that working with Mail.com, Contacts, as examples fall into this category.

it’s not that you cannot do the same things in JXA (actually I put together some automation that I needed for Calendar in JXA a while ago). It’s just that it winds up being a lot harder and sometimes I just cannot figure it out in JXA. I think (as Dr. Drang points out in a recent Automators episode) that this is because there is just so much more in the way of sample code out there for AS vs JXA because AS has been around for so much longer, and the scripting interface is just such a mess. Every app’s dictionary is different and figuring out how to accomplish something is as much trial, error, and guesswork as science - perhaps more.

At least for me as a result, AS is a necessity, and since AS is so poor at handling text in general, building a JSON response is a pain. I suppose I could write a reusable module that takes an AppleScript property list (or whatever AS calls is; I cannot remember) and outputs the JSON, and if I wind up doing this a lot I suppose I will.

1 Like