Finding the right matching list in a JSON string

I was looking at Auto-appending a field, and thought I might try storing lists of mutual synonyms in a JSON tiddler

title: Synonyms
type: application/json

[
  ["Delight", "Joy", "Ecstasy"],
  ["Anxiety", "Stress", "Tension", "Apprehension"],
  ["Gratitude", "Contentment", "Thankfulness"]
]

But I’m not really sure how I could get the list of matching ones. In JS, I’d just do this:

const getSynonyms = (synonyms, term) => 
  synonyms.find(list => list.includes(term)) || []

const synonyms = [
  ["Delight", "Joy", "Ecstasy"],
  ["Anxiety", "Stress", "Tension", "Apprehension"],
  ["Gratitude", "Contentment", "Thankfulness"]
]

getSynonyms(synonyms, 'Stress') //=> ["Anxiety", "Stress", "Tension", "Apprehension"]

My best attempt so far in wikitext is, I believe, not very close:

[{Synonyms}jsonindexes[]] :map[{Synonyms}jsonget<currentTiddler>] :filter[contains[Stress]]

This part, in the Advanced Search, Filter tab:

[{Synonyms}jsonindexes[]] :map[{Synonyms}jsonget<currentTiddler>]

yields the list Delight Anxiety Gratitude, so it seems too late to add a filter step.

Can I use jsonget or something similar to extract a whole list which I can then further process?

Of is there a better way to do this?

We don’t have a good response emoji for “what a great question”. And when you think about it, we really should. There are far more questions than there are answers…

So. Yeah. Great question, @Scott_Sauyet.

1 Like

Hi @Scott_Sauyet here’s one approach:

\procedure jsonSynonyms()
[
  ["Delight", "Joy", "Ecstasy"],
  ["Anxiety", "Stress", "Tension", "Apprehension"],
  ["Gratitude", "Contentment", "Thankfulness"]
]
\end

\function getSynonym(word)
[<jsonSynonyms>jsonindexes[]] :map[<jsonSynonyms>jsonextract<currentTiddler>] :filter[<currentTiddler>jsonget[]match<word>] +[jsonget[]]
\end

\procedure displaySynonym(word)
<p>
Synonyms of <$text text=<<word>>/>: <$text text={{{ [function[getSynonym],<word>join[,]] }}}/>
</p>
\end

<<displaySynonym Stress>>
<<displaySynonym Ecstasy>>
<<displaySynonym Gratitude>>
<<displaySynonym Saudade>>
2 Likes

The first thing that comes to mind is this, which is quite verbose:

[{Synonyms}jsonindexes[]] :map[{Synonyms}jsonextract<currentTiddler>] :filter[jsonget[]match[Stress]] :map:flat[jsonget[]]

2 Likes

I would urge you to look at @pmario’s alias solution in wikilabs library and specifically the uni-link plugin.

  • This solution goes a long way to helping with glossary and synonyms
  • If nothing else for inspiration

This text is to make this post less similar to one I deleted

Tones, just do this in future…

&emsp; &emsp; &emsp;
&nbsp;&nbsp;&nbsp;&nbsp;
&emsp; &emsp;
&emsp;&nbsp;&nbsp; &nbsp;&nbsp;

Invisible.

When the gatekeepers bar you entry, hop over the fence.

Yes, and if you design a gate, always include an emergency button.

Post script;

In a corporate role I was given advanced admin in SharePoint, later with the deterioration of a working relationship (I needed to question his policy) he removed my access without telling me, I could have considered it malicious, but instead I considered it an accident :nerd_face: , and found a way to give myself back the access via a hack. Of course I did not need to inform him. Because he did not intend to lock the gate did he?. So placing a style to get over the fence, would not hurt any one would it?

Thank you both for your (very similar) suggestions. I think I will end up with this version:

\function get.synonyms(term)
[{Synonyms}jsonindexes[]] :map[{Synonyms}jsonextract<currentTiddler>] :filter[jsonget[]match<term>] :map:flat[jsonget[]] +[unique[]] +[sort[]]
\end

I like the :map:flat so that if a term is used in multiple separate lists, both lists will appear. But then I need unique to not double-list.


The following pattern makes me think there’s a missing JSON operator:

[«something»jsonindexes[]] :map[«something»jsonextract<currentTiddler>]

When I find a little time, I will try to write something like

[«something»jsonvalues[]]

to do the same thing, an obvious parallel with JS’s Object.values, unless I’m simply missing existing functionality somewhere.

That is,

\procedure foo() {"a": "Foo", "b": "Bar", "c": "Baz"}

{{{ [<foo>jsonvalues]}}}

would yield

Foo Bar Baz

And

\procedure bar() ["Qux", "Corge", "Grault"]

{{{ [<bar>jsonvalues]}}}

would yield

Qux Corge Grault

Would this make sense?

While I think it’s not quite a match for the current problem, I have a few wikis on which I will install this straightaway. It looks extremely useful, and I wish I had seen it a year ago!

{{{ [<foo>jsonget[]] }}}

Ahh, ok. I had only seen that used to extract a list of values.

I don’t find that usage in the documentation. This is the end of the current docs:

A subtlety is that the special case of a single blank operand is used to identify the root object. Thus:

[<jsondata>jsonindexes[]] --> "a", "b", "c", "d"

which looks like a bad copy-paste from jsonindexes. The prerelease updates this documentation, but doesn’t address this gap. I’ll try to find the PR and report it there.

Update

I misremembered. It’s the jsonset documentation which has been updated, not this one. @jeremyruston: Is it too late to get in a docs change for the upcoming release?

That also simplifies my function substantially:

\function get.synonyms(term)
[{Synonyms}jsonget[]] :filter[jsonget[]match] :map:flat[jsonget[]] +[unique[]] +[sort[]]
\end

Oops, didn’t save the changes before testing. This does not work in my case. It’s interesting to see, though, and I’ll have to figure out where it’s helpful.

One behaviour of the jsonget operator that may be a surprise is the way that it handles returning arrays or objects whose members are not strings. Because the jsonget operator always returns regular strings, rather than JSON, in that situation it recursively returns all the values.

This is the relevant example from the docs:

[<jsondata>jsonget[d],[f]] --> "five","six","true","false","null"

In other words,jsonget is only useful for reading a JSON array as a list if that array is entirely composed of strings.

Docs updates for existing features can even be pushed independent of releases. So please do feel free to create a PR targeting the tiddlywiki-com branch.

I did see that bit of the docs, and tucked it away, although I can’t think of too many good uses.

But there seems to be nothing in the docs that really suggest what jsonget[] with an empty parameter returns.

I literally just tried it. <shrug>

If anyone is curious, here is how I used this: http://scott.sauyet.com/Tiddlywiki/Demo/UsingSynonyms.html.

1 Like