Hi @jeremyruston, here is my first quick stab at an <$action.setjson> widget, written completely in WikiText:
\widget $action.setjson($tiddler)
<!-- if any intermediate levels are not given, they are assigned the "0" index -->
\define defaultIndex() 0
\function thisLevelIndex() [<widgetParameters>jsonget<level>else<defaultIndex>]
\function previousLevel() [<level>subtract[1]]
\define check-success() [jsonextract<setLevel>match<setValue>]
<!-- we try to assign the value as a JSON object and fall back to string assignment if that fails (e.g. when assigning the actual "value" parameter) -->
\function .json-then-string(setLevel,setValue) [all[]jsonset:json<setLevel>,<setValue>filter<check-success>] :else[all[]jsonset:string<setLevel>,<setValue>]
<!-- we iterate (in reverse order) and build up the multi-level JSON object -->
\function .jsonBuilder(level) [<level>compare:integer:gt[0]] :then[all[].jsonBuilderInner<level>else[]] :else[all[]]
\function .jsonBuilderInner() [all[]] :map[[].json-then-string<thisLevelIndex>,<currentTiddler>] +[.jsonBuilder<previousLevel>]
<$parameters $params="widgetParameters", 0=<<defaultIndex>> >
<$let input={{{ [<$tiddler>type[application/json]get[text]format:json[]] }}}
level={{{ [<widgetParameters>jsonindexes[]search::regexp[^\d+$]maxall[]] }}}
value={{{ [<widgetParameters>jsonget[value]jsonstringify[]] }}}
jsonObject={{{ [<value>.jsonBuilder<level>] }}}
output={{{ [<input>.json-then-string<0>,<jsonObject>] }}}
>
<!-- this is for debugging when not used as an action -->
<$codeblock code={{{ [<output>format:json[4]] }}} />
<% if [<$tiddler>type[application/json]] %>
<$action-setfield $tiddler=<<condition>> text={{{ [<output>format:json[4]] }}} />
<% endif %>
</$let>
</$parameters>
\end
This will set a string value at a position in the JSON hierarchy which is defined by integer parameters, starting at 0 like so:
<$action.setjson $tiddler=<<jsonTiddler>> value="This is some text." 0=h 1=i 2=j />
The nested hierarchy is created if it does not exist, e.g. if there is no existing index “h” in the above example. If hierarchy levels are omitted in the parameters, they are still created with a default index value of 0.
If anyone wants to play around with this, I made a Sharing Edition.
PS: I realized that this will completely overwrite anything that is already assigned the 0-level index. Therefore, this widget couldn’t be used in its current state to insert some property somewhere in the deeper structure of the JSON object. I’ll try to fix this, but this might be non-trivial and may require a different approach.
I did try this, as a simple variation of jsonset. The code has a very different style from TW core, so is not right for the core, but that would be easy enough to fix. If the current behavior is a bug, as Jeremy says above:
You can try this by downloading the following, dragging it to a wiki, saving and reloading, then opening the jsonDeepSet Test tiddler:jsonDeepSet.json (4.0 KB).
The key is to allow the use of variables, and the syntax of variables should not conflict with other syntax. This can be challenging in JSON with multiple levels. Additionally, I believe that fields with deeper values are worth exploring. However, this would undoubtedly increase the workload, as many widgets may require refactoring or the addition of new code. Therefore, I think prioritizing JSON or data entries is a better approach.
There are indeed some scenarios where deeper field levels may be necessary. For example, when working with Markdown files that contain multi-level YAML content, converting these files to TiddlyWiki can be quite challenging.
Of course, a combined approach is also possible. For instance, the field content of a particular entry could be fully controlled by another JSON tiddler, with the text body excluded from it.
Of course there are potential issues if the keys contain .'s, but I think it’s mostly a reasonable approach. That’s clearly related to my alternative API above.
Maybe my ignorance is showing through here, but a number of solutions exist that resemble what is being asked for here, and the depth of understanding to make true comparisons or analysis of the options available is difficult for me (at present). For Example I was just looking at @FlibblesIntroducing TW5-Graph, Tiddlymap's spiritual successor! which quickly leads to the prior work on XML and the xpath and xselect widgets and filter operators.
For me I need to commit some time to become more familular with XML and @Flibblestools to manipulate them, before I can understand it enough to extrapolate its application in tiddlywiki, and specficaly as an alternative to, or simplifying structured JSON.
Only then will I be in a place to compare and contrast it with the issues here
Can you help
If you already have a good understanding of JSON/XML and these tools please have a look and tell us what you think.
The best approach?
It seems to me we need to try and bring together a disparite set of data representation, queries and manipulation and try and use convergence to make skills developed in tiddlywiki or anyone of these global standards applicable accross others. There by “steepening the learning curve” ie: making each quicker to learn and adopt (Note: the correct use of the often missused slope of the learning curve)
On key value pairs
That is fine to say but as this topic demonstrates JSON management is incomplete.
Not the core fine, but it needs to be core adjacent. See my next point.
This concerns me in so far as I accept this may be depricated in the tiddlywiki core, and we may not wish to promote the use of Data tiddlers, however even when depricated, tools to use to manage and manipulate datatiddlers are essential even if just to assist in migrating away from data tiddlers.
However I also think we are over looking something and that is TiddlyWiki participates in the global internet, app, software and data ecosystem, and regarless of what is chosen to be core behaviours in tiddlywiki there is a whole universe out there. That is it will often be the case than key value data is available out there or used out there and will always be needed as are the import and export and manipulation of such data.
Even if at a minimum it is imported and;
Converted to JSON
Converted to tiddlers and fields
Converted to XML
Although the Data Tiddler concept is realy just a “file” of rows or key value pairs, and is one of the easier structures for novice users to understand. To “remove this” is to deminish TiddlyWiki.
Right now, you’ve got text/x-tiddler-dictionary, and you can index and modify it using things like ##key.
And then there’s application/json which accepts ##jsonKey and such again for single-level objects fetching and setting.
If dataTiddler logic were in modules, then a plugin could make indexing support JSONPath, which would make setting entires in a json tiddler’s tree as simple as:
which would neatly set all json paths that match that pattern. The dollar sign is a standard of JSONPath, I think, which would help preserve backward compatibility.
Just a thought. I know DataTiddlers are kinda passe.