How can I use JSON to define a menu and submenu structure?

If I have a simple database:

A: name1
B: name2
C: name3

There's one to many relationship to:
A1: value1
A2: value2
B1: value3
B2: value4
C1: value5
...

I wanna use prompt list action to achieve when I click A, it shows A1 and A2 on another prompt list menu, then click A2, I need to insert text "value2" on any place.

I try to use a external json file as my input, anyone can help me finish the code? Thank you in advance!

Have you started it ?

One possibility might be this kind of macro, which requires you to have a subroutine in the macro group, as well as the macro itself:

Menu from JSON subroutine.kmmacros (3,0 Ko)

MENU from JSON.kmmacros (3.5 KB)



Expand disclosure triangle to view JS source
const dictOrArray = JSON.parse(kmvar.menuJSON);

return Array.isArray(dictOrArray)
    ? dictOrArray.join("\n")
    : Object.keys(dictOrArray).map(
        k => `${JSON.stringify(dictOrArray[k])}__${k}`
    )
        .join("\n")

Thank you for your coding.

My json structure is like below:

{
  "A__1.aaa": {
    "A1__1.a1": "A1AAAAA",
    "A2__2.a2": "A2AAAAA",
    "A3__3.a3": "A3AAAAA"
  },
  "B__2.bbb": {
    "B1__1.b1": "B1BBBBBB",
    "B2__2.b2": "B2BBBBBB",
    "B3__3.b3": "B3BBBBBB"
  },
  "C__3.ccc": {
    "C1__1.c1": "CCCCfCC",
    "C2__2.c2": "CCCfCCC",
    "C3__3.c3": "CCCCsCC"
  }
}

For example, if choose submenu "A2__2.a2", I should get the value "A2AAAAA".

It might be better to preprocess your JSON to a different pattern – the double underscores there (__) clash with the syntax of Keyboard Maestro menu strings.

What do you want the menus and submenus to display ?

Lists like:

  • B1
  • B2
  • B3

?

or the full:

  • B1__1.b1
  • B2__2.b2
  • B3__3.b3

?

I displayed as:

  • 1.b1
  • 2.b2
  • 3.b3

B1__ is used for switch like:

switch
if result="B1": .....
if result="B2": .....

Anyway, I think now it's no need to use switch like that, just show B1, B2, B3 is ok.

As @ComplexPoint says, the double-underscores mess things up -- the leading characters, eg "A", won't be displayed in the prompt but will be the only thing returned by the prompt. I've used your original JSON, but included a "Search and Replace" to swap them all for single underscores.

Then it's just a case of listing all the "top level" keys, picking one, listing all the keys for that choice, and combing the two chosen keys into a path to get the result:

Database(ish).kmmacros (6.4 KB)

Image

There's probably quicker/cleaner ways to do this -- for a large "database" it might be better to work on only the match from the first choice rather than search the whole blob again -- but I'm so bad at JSON that I'm glad to get to "working" and not worry about "optimal" :wink:

2 Likes