Alternative Ways to Read JSON Data

idk …but it sounds a bit like
:safety_pin: :eyes: :left_speech_bubble:
Transforms every database into a object key value store. - ether/ueberDB

Database Support
Couch
Dirty
Elasticsearch
Maria
memory: An in-memory ephemeral database.
Mongo
MsSQL
MySQL
Postgres (single connection and with connection pool)
Redis
Rethink
rustydb
SQLite
Surrealdb

@wiki_user … Stuff like this does not really make any sense for TW. It would add a 13MByte package to a tiddlywiki single file wiki, for no win. ./dist/index.js would have to be included.

i get that is not practical in standalone.html context

but also i think you get it is (or appears to be/if i understand the comment context correctly ) a
(simpler) implementation of a similar db-adapter concept

not practical in standalone context

makes me wander about what
usage metrics might be for such different cases
(though id guess that data is not practical to attain )

I am talking about how to address the current store of tiddlers not changing how we store them.

I’m just realizing that I never responded to this. My point was that we can’t do this unambiguously, since any string is an acceptable JSON key. In the following [a],[b.c],[d] could reasonably have value 1, 2, 3, or 4.

{
    "a": {
        "b.c" : {
            "d":  1
         },
        "[b.c]" : {
            "d": 2
        },
        "[b.c],[": {
            "d]": 3
        },
        "... and many": "more"
    } ,
    "[a],[b.c]" {
        ",[d" : {
            "]": 4
        }
    },
    "etc., etc": "etc"
}

That’s not necessarily a show-stopper. If you have such crazy keys, you’ll have to explicitly specify them, and not use this new index mechanism.

Your proposed rules would unambiguously choose a value, if the path exists in the object. But there are a number of legal keys it could not handle.

It does get a little squirrely.

Doesn’t this mean that the current jsonget parameter handling also has the same limitation?

My proposal simply makes the current jsonget reference handling syntax available for use in the $transclude widget, so instead of writing:

<$let value={{{ [[SomeJSONTiddler]jsonget[a],[b],[c],[d]] }}}><<value>></$let>

you can write:

<$transclude $tiddler="SomeJSONTiddler" $index="[a],[b],[c],[d]"/>

It also occurs to me that this same enhanced $index handling could also be useful in $action-setfield. Consider… to update a value in a JSON tiddler, you currently need to fetch a tiddler’s text field value, apply jsonset to that value, and then use $action-setfield to re-write the text field, like this:

<$let old={{{ [[SomeJSONTiddler]get[text]] }}}
      new={{{ [<old>jsonset[a],[b],[c],[d],<somevalue>] }}}>
<$action-setfield $tiddler="SomeJSONTiddler" text=<<new>>/>
</$let>

Even if you combine these steps in single widget, it’s still a somewhat awkward (and error prone) syntax:

<$action-setfield $tiddler="SomeJSONTiddler"
   text={{{ [[SomeJSONTiddler]get[text]jsonset[a],[b],[c],[d],<somevalue>] }}}/>

compared with:

<$action-setfield $tiddler="SomeJSONTiddler" $index="[a],[b],[c],[d]" $value=<<somevalue>>/>

-e

1 Like

No. The issue is when you combine the nested keys into a single string. If you have separate keys for each level, there is no issue.

There is some complexity, which is similar to what happens in our regex handling. If your keys contain square brackets or other characters not allowed in a hard parameter, you would need to put them in a variable:

<$let key1="[b.c],[", key2="d]">
    {{{ [[SomeJSONTiddler]jsonget[a],<key1>,<key2>] }}}
</$let>

But we should be able to address any nested JSON properties using that. For the reasons I’ve already mentioned, any attempt to combine the keys into a single string will not allow for this universality.

That doesn’t mean that it’s a terrible idea. But we shouldn’t go into this without understanding the limitations.

Even more so if the key is realistically driven by variables jsonset<a>,<b>,<c>,<d> This is a critisisum of mine about the Tiddlywiki documentation, most examples have literals not variables, fields or transclusions. Kind of an example how to go to the library and get a specific book out, but not teach you how to get any book in the library :smiley:

Ah. But my proposal doesn’t “combine the nested keys into a single string”:

If the $index param doesn’t contain square brackets, it’s handled as a single top-level key. If it does contain square brackets, it’s handled the same as the jsonget filter parameters (i.e., “separate keys for each level”).

-e

I’m pretty sure it does, unless I’m drastically misunderstanding your proposal. You say, for instance:

That’s now a single string, instead of, say, the three strings "a", "b.c", and "d".

I’m almost certain that any way you choose to combine them into a single string won’t be able to cover all legal JSON.

For this example, how would you distinguish between the paths to 1 and 2 in this?:

{
    "a": {
        "b.c" : {
            "d":  1
         },
    } ,
    "a],[b.c" {
        "d" : 2
    }
}

Wouldn’t both of them be given by [a],[b.c],[d]?


I’m not suggesting that we don’t do this. But if we do, we need to be careful about documenting the sorts of key structure we can support. “Not abnormal”, for some definition of “abnormal”, I guess. :wink:

Perhaps we can have an interving macro or custom widget or genesis widget to suppor the key structuring?

Such as

<$get-json-item L1keyname=<<var1>> L2keyname=<<var2>> L3keyname=<<var3>> >
and the result is also returned in here as <<L1value>>, <<L2value>>, <<L3value>>
 </$get-json-item>

and let that handle the composition of the key. In this example we may only want to use <<L3value>>

I think we’re talking past each other…

Obviously, the syntax I am suggesting uses a single $index="..." parameter.

However, what I am proposing is that, if the $index parameter contains square brackets, it should be parsed using the same logic as the jsonget filter parameters, where it would be unambigously treated as three bracketed, comma-separated keys, "a" , "b.c" , and "d".

The example you’ve given that uses two keys: “[b.c],[” and “d]” requires extraordinary effort to bypass the normal jsonget operator’s “bracketed key” parsing by using variables. I would argue that this is clearly an “abnormal” use case that we don’t need to consider within the scope of this proposal.

-e

edit:
My proposal could be made to handle “abnormal” usage by changing the suggested parsing strategy just a little so that it doesn’t depend upon the use of square brackets to trigger the secondary parsing logic:

  • First, attempt to use the entire $index parameter value to retrieve a top-level key (as it currently does).
  • If that fails to return a result, then use the $index parameter value as if a jsonget filter operator were being processed.

Thus, it would permit the use of variables so you could write $index="<key1>,<key2>" to handle your odd example where the key values contain square brackets.

-e

1 Like

If you do that, you don’t run into the issue I’m describing, but you also don’t get the convenience that Eric is seeking. That is still a list of separate node names.

Yes, and it would get progressively sillier the more sophisticated the operator logic became. But I’m pretty certain that it would always remain possible to construct such ridiculous keys no matter our level of sophistication.

Yes, I can certainly live with that, should we decide to go this route, We’d simply need some reasonable documentation about the limitations. But I’m not sure this really adds all that much convenience to our current capability.





If you want to see a long, drawn-out argument about this, I participated in one fifteen years ago. I wouldn’t recommend it.

As I said, I believe we could just keep thinking of JSON keys that would break any such attempt. How would we address 1 in this?:

{
    "a": {
        "b": 1
    },
    "[a],[b]": 2
}

Also, there is an eval problem lurking in here. By placing what is essentially source code into a string, we escape many of the protections offered by a parsing step. To address 42 in this:

{
   "[[": {
        "]]": 42
    }
}

We’d end up trying to handle [[[],[]]], and I have no idea what would happen, likely a serious error, even though that JSON string parses just fine to a legal JS object.

I believe that rather than trying to come up with an unambiguous syntax, we would be better off documenting its restrictions. That is, if we proceed at all, which I’m not convinced of.

As I typed that, I thought of another possibility: use the same string-escaping technique used by the source code of JS and other C-style languages. We choose an escape character, likely \, and then note the characters with special meaning in our syntax—above that’s ,, [, and ]—and then require those characters and the escape character itself to be preceded by the escape character whenever they are meant literally; any other escaped characters just pass through. In the above 1 is addressed by [a],[b] and 2 by \[a\]\,\[b\]. I do not immediately see any key structure we couldn’t handle this way, although I wouldn’t be surprised if they exist. This doesn’t offer any solution to the parsing problem mentioned above. And I’m still not convinced that it’s worth doing.

My first inclination is to wonder WHY anyone would deliberately use BOTH a literal JSON key like “[a],[b]” AND separate nested “[a]” and “[b]” keys in the same JSON data? It really seems to me that you are trying very hard to suggest ambiguous JSON which will rarely (if ever) occur for any practical use-case.

Nonetheless, for this theoretical “degenerate” JSON, the existing jsonget[a],[b] operator would return “1” since its normal parsing will always treat the square brackets and commas syntax as indicating separate nested key values, while the existing $index="[a],[b]" usage would return “2” since it always treats the specified $index as a single top-level key value.

Note that the only way that jsonget could ever return “2” would be by using a variable to defeat its normal parsing and force it to treat [a],[b] as a single top-level key:

<$let weirdkey="[a],[b]">{{{ [{!!text}jsonget<weirdkey>] }}}</$let>

-e

I would certainly hope they wouldn’t!

Yes, I thought I’d said as much. But it’s not that I would expect users to use such crazy JSON files; they are just convenient examples to demonstrate that there are ambiguities in any way we try to write single-string paths in a JS object. Because any string can be a legal key, it just gets crazy.

My basic take is this: I’m happy enough with the jsonget multi-parameter approach. I see no reason to try to add a single-parameter one. Still, I have no major objection to one, if people really want it. But if we do it, we need to very carefully document the restrictions on the sorts of JSON structures it can support. Because they could never be universal. (Unless my escape-character solution actually does work.)

1 Like

The OP (@Ben) for this discussion was here:

where Gemini LLM suggested:

<$transclude tiddler="test.json" index="d.e"/>

which doesn’t work because the $transclude widget can only access single-level JSON key/value pairs (i.e., no nested JSON structures at all).

After explaining the use of jsonget[], I began thinking that:

it might be a nice TWCore enhancement if the syntax suggested by Gemini actually could produce results for nested JSON objects

and @Ben followed with

Is it possible to use the jsonset Operator in a button for example to change the value?

This then lead to the ongoing discussion about how the JSON filter operators are somewhat complicated and that perhaps we could implement a simpler syntax that would allow people to use $transclude and $action-setfield with nested JSON objects without needing to use filter syntax at all.

In particular, in this post: Alternative Ways to Read JSON Data - #11 by EricShulman I compared the current filter-based syntax with some possible alternatives. Sure, they are really just “syntactic sugar”… but that’s often what makes things MUCH easier for people to understand, especially if they are not experienced coders (which is, after all, one of the goals of TiddlyWiki… to make complex tech more accessible).

-e

1 Like

Yes. I’d been following along, and that is where I jumped in.

My conclusion was in

my most recent post

I don’t deny that this syntactic sugar is sweet. But I don’t want us to pretend that it’s a proper meal. I think that if we do choose to do it, we need to make the limitations clear.

Background

In an unrelated research exercise, I am looking at building an easy way to manage relationships between tiddlers. In its simplest form, one tiddler can name another in a field. eg; “person tiddler”, sets spouse=“spouse tiddler”, and we can even get the “spouse tiddler” to discover its spouse using the no touch methods in my flags POC. In many cases this may be sufficient.

However what if “person tiddler” has more than one spouse over time? Where the spouce field is a list field, In that case we may want to store other details about that specific relationship such as mariage and divorce dates.

Relavance to here?

I was hoping to store these extra details about a relationship, in a JSON tiddler with a compond key eg spouse/person-tiddler/spousetiddler then store additional details like dates for start/end of the relationship.

  • If I am honest I belive the cognative load to achive this in JSON, would be immense, especialy with current JSON tools and the aformentioned key issues.
  • I stand to be corrected, but it also raises questions if attempting to retain referential integrity with changes to relationships. Such as if “person tiddler” changes their name as a result of the start/end of the relationship. Common in many cultures.

Realisation

I have explored a solution using tiddlers to represent such relationships such as $:/spouse/person tiddler/spouse tiddler and this is very powerful.

The key realisation here is, If I use tiddler titles, I have a large suite of filter operators that let me handle such relationships. So I can find any relationship details whatever information is available to me for example;

  • prefix[$:/spouse/person tiddler] all “person tiddlers” spouse relationships
  • [prefix[$:/spouse]suffix[/spouse tiddler]] spouse tiddler’s spousal relationships
  • [suffix[/spouse tiddler] all “spouse tiddler” relationships (also flag mechanisium)

Conclusion

Perhaps if we had filters that would allow us to interogate a JSON tiddlers with these partial keys, I could push this design into one JSON tiddler. Keeping relationships within a single tiddler.

Is this making sense?

Note: because “Relationship” could easily have two very distinct meanings in the discussion, I am going to use “Marriage” as the term for any committed long-term romantic/sexual pairing, regardless of whether there are wedding vows involved. This frees “Relationship” to represent the various structured interconnectivities between tiddlers or other entities.

My personal preference for this is to use additional tiddlers. A single JSON tiddler might possibly work, but I think such relationship tiddlers often are worthy of inspection on their own. Often I will have ViewTemplates for them.

So perhaps I might have some Hollywood listing that included marriages between celebrities, (including Elizabeth Taylor) with Person tiddlers such as these:

+------------------------+    +------------------------+    +------------------------+
| title: id/12345        |    | title: id/45678        |    | title: id/67890        |
| tags: Person           |    | tags: Person           |    | tags: Person           |
| name: Richard Burton   |    | name: Conrad Hilton    |    | name: Mike Todd        |
| ...                    |    | ...                    |    | ...                    |
+------------------------+    +------------------------+    +------------------------+
						 	 						                                
+------------------------+    +------------------------+    +------------------------+
| title: id/23456        |    | title: id/56789        |    | title: id/78901        |
| tags: Person           |    | tags: Person           |    | tags: Person           |
| name: Eddie Fischer    |    | name: Elizabeth Taylor |    | name:  John Warner     |
| ...                    |    | ...                    |    | ...                    |
+------------------------+    +------------------------+    +------------------------+
						 	 						                                
+------------------------+    +------------------------+    +------------------------+
| title: id/34567        |    | title: id/67890        |    | title: id/89012        |
| tags: Person           |    | tags: Person           |    | tags: Person           |
| name: Larry Fortensky  |    | name: Mike Todd        |    | name: Michael Wilding  |
| ...                    |    | ...                    |    | ...                    |
+------------------------+    +------------------------+    +------------------------+

and Marriage tiddlers such as these:

+---------------------------+    +---------------------------+
| title: id/3210            |    | title: id/7654            |
| tags: Marriage            |    | tags: Marriage            |
| people: id/56789 id/45678 |    | people: id/56789 id/12345 |
| married: 1950             |    | married: 1964             |
| divorced: 1951            |    | divorced: 1974            |
| ...                       |    | ...                       |
+---------------------------+    +---------------------------+
                                 
+---------------------------+    +---------------------------+
| title: id/4321            |    | title: id/8765            |
| tags: Marriage            |    | tags: Marriage            |
| people: id/56789 id/89012 |    | people: id/56789 id/12345 |
| married: 1952             |    | married: 1975             |
| divorced: 1957            |    | divorced: 1976            |
| ...                       |    | ...                       |                        
+---------------------------+    +---------------------------+
                                 
+---------------------------+    +---------------------------+
| title: id/5432            |    | title: id/9876            |
| tags: Marriage            |    | tags: Marriage            |
| people: id/56789 id/67890 |    | people: id/56789 id/78901 |
| married: 1957             |    | married: 1976             |
| ended-in-death: 1958      |    | divorced: 1982            |
| ...                       |    | ...                       |
+---------------------------+    +---------------------------+
                                 
+---------------------------+    +---------------------------+
| title: id/6543            |    | title: id/0987            |
| tags: Marriage            |    | tags: Marriage            |
| people: id/56789 id/23456 |    | people: id/56789 id/34567 |
| married: 1959             |    | married: 1991             |
| divorced: 1964            |    | divorced: 1996            |
| ...                       |    | ...                       |
+---------------------------+    +---------------------------+

I think this technique addresses this point:

It takes this on directly, since people’s names are not the titles for our tiddlers. Instead we use some sort of opaque id, perhaps a sequence number, and perhaps a GUID, and perhaps even the value of some external id . I often choose instead of a single namespace as shown here, to have a namespace for each identity, for instance, Person/1, Person/2, … and Marriage/1, Marriage/2, … Either way is fine; the single-namespace avoids some duplication, but is less clear at a glance.

It also addresses this point

Tiddlywiki has a rich querying language for tiddlers. It does not have one for objects stored as JSON strings. JavaScript does. If we were doing things in JS, then such a store might be useful. In wikiscript it just makes sense to use tiddlers.

1 Like