Accessing JSON dictionary content with variable

Hello everyone!

This is my first post in this forum. Looking forward to joining this friendly and helpful community! Please feel free to provide any feedback about how to create more meaningful posts.

Short-term objective: I want to access a nested JSON object (more complex than the one in this example ... but let's start simple for now) using a variable which is used as pointer to a specific (but changing) entry in the JSON dictionary.

Long-term objective (not part of the example macro shown here -> not directly relevant to answer this post but might be useful information to propose alternative approaches): I want to be able to quickly save emails from Apple Mail as pdf documents to specific folders. The folders shall be selected automatically based on the email address of the sender (e.g., if the email is from my bank, the Save As dialogue should automatically switch to the corresponding folder containing my bank documents). To have the "Save as" dialogue automatically switch to the relevant folder, I want to use a JSON containing multiple entries (also used for other purposes) containing the mail-address and the corresponding folder path for all frequently received emails.

I am relatively new to JSON. I read the manual page (especially the part about the JSON Paths) but it seems my JSON knowledge does not yet allow me to transfer the info from the manual to my specific use case.

The following macro contains two groups. The first group contains the direct approach to access the JSON content. The second group contains the attempt to access the JSON dictionary indirectly via the content of the pointer variable.

As other users might experience the same problem, I kept a history of all failed attempts in the macro. Actions colored in red do not yield the expected result.

Any help is greatly appreciated.

Here is the example macro:

Accessing JSON dictionary content with variable.kmmacros (5.5 KB)

1 Like

Since you're using the %JSONValue% token, start with this page of the Wiki -- the examples are more directly applicable to your test macro.

While KM "will use arrays and dictionaries more or less interchangeably" you still have to match the data structure of the JSON -- you have a Dictionary, and you can't use array access methods since Dictionaries are "unordered".

You also have an unwanted . in your {}-containing actions.

So for your first failing action, this:

%JSONValue%J.{2}%

Should be:

%JSONValue%J{second}%

...or:

%JSONValue%J.second%

As to using a variable...

A text field is evaluated from left to right, and there is no evaluation of nested tokens (that may not be an absolute rule -- anyone care to chip in?). So while you'd expect this:

%JSONValue%Local_J{%Variable%Local_getter%}%

...to work, coz surely it gets to J{, evaluates the Local_getter variable, then uses that result to continue evaluating JSONValue -- it doesn't.

While there may be tricks to get round this it is probably better to do things explicitly, unpacking layer-by-layer by escaping tokens you don't want to be evaluated yet and processing the rest. So you'd start the above example by escaping the JSONValue token and processing Local_getter:

%%JSONValue%%Local_J{%Variable%Local_getter%}%%
-          -                                 -

(I've underlined the extra, escaping, % characters).

Say Local_getter contains second. The above will evaluate to:

%JSONValue%Local_J{second}%

...and notice how the escaping %s are also removed -- every %% token is processed to %.

You then evaluate that again to get the value of the second key of your JSON Dictionary, using the "Filter: Process tokens" action.

Putting that all together, with a "Prompt for User Input" so you can test (and using local variables so as not to pollute your namespace):

Accessing JSON dictionary content with variable demo.kmmacros (5.0 KB)

Image

Hello Nige_S,

What can I say ... that is impressive stuff. Thank you!!!

I will need some more time to process your explanation in its entirety but I think I got the gist of what you are proposing.

  • Using %% instead of % prevents the parsing engine to interpret the code following it. You did this with the outer %-signs but not with the %-signs for the innermost variable. Thereby, only the innermost variable is interpreted and %Variable%Local_getter% is converted into "second".

In your example ...
%%JSONValue%%Local_J{%Variable%Local_getter%}%%
is converted into
%%JSONValue%%Local_J{second}%%

  • You then use the "filter variable with process token" action to basically replace each %% with a single %.

In your example ...
%%JSONValue%%Local_J{second}%%
is converted into
%JSONValue%Local_J{second}%

  • In your last step, you simply evaluate the resulting variable (containing "%JSONValue%Local_J{second}%" and display it as text ... which results in the content of the selected key-value-pair from the initial JSON (result depends on which key has been selected by the user).

Hope this summary is more or less correct. Please let me know in case I made any incorrect interpretation.

As I said in the beginning ... very impressive. I would have never thought about this myself. Thanks a lot! Now I will try to implement this into my actual use case. Let's see how that goes.

Not quite. The escaped % -- %% -- is also a token so gets evaluated to % in the first pass:

%%JSONValue%%Local_J{%Variable%Local_getter%}%%
-->
%JSONValue%Local_J{second}%

Note how the double %s are now singles.

That's now a properly-formatted %JSONValue% token -- when the "Filter" action process that it will evaluate the token and put the value of the Dictionary item with the key second into the variable Local_test.

The final action displays the value of Local_test in the usual way.

Thank you, Nige_S, for the additional explanation! Honestly, I will need to play around with token processing a bit more to fully understand this. In any case, I could not have solved this problem without your help. Thanks a lot, again!