More help needed with json tiddlers

Hello TW community,

There have been several discussions recently about how to deal with JSON tiddlers (reading, dealing with object structure, deleting, …).

However I am missing some elements to join the dots.

More especially I would like to create / read / write / update JSON tiddlers that contains a set of tiddlers with some selected set of their fields. For instance:

{
    "A tiddler": {
        "icon": "my-icon",
		"color" : "#fedcba"
	},
    "Another tiddler": {
        "icon": "another-icon",
		"color" : "#abcdef"
	}
}

How can I achieve the following use case:

  1. add a tiddler with a set of defined fields inside the json data tiddler
  2. add a field name and value to a tiddler already in the json data tiddler
  3. update the field value of a givent tiddler inside the json data tiddler
  4. extract the list of tiddlers title present in the json data tiddler
  5. extract the field name of a tiddler present in the json data tiddler
  6. extract the field value of a tiddler present in the json data tiddler
  7. remove a field name and value from a tiddler present in the json data tiddler
  8. remove a tiddler present in the json data tiddler

All this action would be triggered using buttons.

BR,

Eskha

1 Like

Most of the content is replicated below, but I’ve created a tabbed tiddler with the answers:. You can download the following, drag it to any wiki and import the tiddlers. Then the tiddler JSON Question should show examples of doing each of these (except that the deletes aren’t really working well before 5.4.0.)

JsonQuestions.json (9.1 KB)

Before we get to answering the individual questions, we have some notes.

General Notes

We create a new JSON string

When we do our manipulation, we don’t directly alter the content of that tiddler. We create a new JSON string. This is important to note. It takes a second step to update the original, if that’s what we want.

For a second step, we could do this:

<$button>Add new object to MyJson
  <$let result={{{ 
    [{MyJson}] 
      +[jsonset:object[A third tiddler]] 
      +[jsonset[A third tiddler],[icon],[icon3]]
      +[jsonset[A third tiddler],[color],[#facade]]
      +[format:json[4]]
    }}} >
    <$action-setfield $tiddler="MyJson" $value=<<result>> />
  </$let>
<$button>

We could combine these into a single action like this:

<$button>
  Add new object to MyJson
  <$action-setfield $tiddler="MyJson" $value={{{ 
    [{MyJson}] 
      +[jsonset:object[A third tiddler]] 
      +[jsonset[A third tiddler],[icon],[icon3]]
      +[jsonset[A third tiddler],[color],[#facade]]
      +[format:json[4]]
  }}} />
<$button>

The parameters can be any wikitext values.

We are not limited to hard-coded values like [A third tiddler], [icon] and [#facade]. We can use other reference, such as variables <title> or <medium-pink> or tiddler field references such as {!!main-icon} or {some tiddler!!icon}.

So we might include a line like this:

      +[jsonset{!!title},[color],<medium-pink>]

Little white-space.

By default, there is no unnecessary white space in JSON output. I add +[format:json[4]] to the display of of each filter here so they are easy to read. But in general, this is only necessary if the result is going to be put somewhere you’re going to be viewing the JSON directly. Otherwise, default output like this is perfectly usable for tools that work with JSON:

{"A tiddler":{"icon":"my-icon","color":"#fedcba"},"Another tiddler":{"icon":"another-icon","color":"#abcdef"},"A third tiddler":{"icon":"icon3","color":"#facade"}}

The object in a JSON string do not have to be tiddlers

The questions seemed to assume that what you store in JSON is always tiddlers. While there are many such uses across TW, what is stored in JSON strings can be arbitrary data.

This would be perfectly legitimate JSON data:

{
    "books":[
        {
            "isbn":"9781593279509",
            "title":"Eloquent JavaScript, Third Edition",
            "subtitle":"A Modern Introduction to Programming",
            "author":"Marijn Haverbeke",
            "published":"2018-12-04",
            "publisher":"No Starch Press",
            "description":"JavaScript lies at the heart of almost every modern web application...",
        },
        {
            "isbn":"9781491943533",
            "title":"Practical Modern JavaScript",
            "subtitle":"Dive into ES6 and the Future of JavaScript",
            "author":"Nicolás Bevacqua",
            "published":"2017-07-16",
            "publisher":"O'Reilly Media",
            "description":"To get the most out of modern JavaScript, you need...",
        }
    ]
}

Note that this isn’t tiddler data, and there is more than one level of nesting.

Answers

We do this by first adding an empty object, and then setting its properties individually:

Code

[{MyJson}] 
  +[jsonset:object[A third tiddler]] 
  +[jsonset[A third tiddler],[icon],[icon3]]
  +[jsonset[A third tiddler],[color],[#facade]]

Result

{
    "A tiddler": {
        "icon": "my-icon",
        "color": "#fedcba"
    },
    "Another tiddler": {
        "icon": "another-icon",
        "color": "#abcdef"
    },
    "A third tiddler": {
        "icon": "icon3",
        "color": "#facade"
    }
}



Code

[{MyJson}] 
  +[jsonset[A tiddler],[favorite-animal],[manatee]]

Result

{
    "A tiddler": {
        "icon": "my-icon",
        "color": "#fedcba",
        "favorite-animal": "manatee"
    },
    "Another tiddler": {
        "icon": "another-icon",
        "color": "#abcdef"
    }
}



Code

[{MyJson}] 
  +[jsonset[A tiddler],[color],[#facade]]

Result

{
    "A tiddler": {
        "icon": "my-icon",
        "color": "#facade"
    },
    "Another tiddler": {
        "icon": "another-icon",
        "color": "#abcdef"
    }
}



Code

<<list-links "[{MyJson}jsonindexes[]]">>

Result



The question seems unclear. Which field name to you want to extract? This will give you a list of them:

Code

<<list-links "[{MyJson}jsonindexes[A tiddler]]">>

Result



Code

[{MyJson}]
  +[jsonget[A tiddler],[color]]

Result

#fedcba



This one is harder. There is a missing jsondelete operator, expected to be included in 5.4.0

Code - not working in 5.3.x

[{MyJson}] 
  +[jsondelete[A tiddler],[icon]]

Result - will eventually look like

{
    "A tiddler": {
        "color": "#fedcba"
    },
    "Another tiddler": {
        "icon": "another-icon",
        "color": "#abcdef"
    }
}

More options are in the thread Delete JSON Object.



Similarly, this is not available for working with a JSON string. But if you want to directly update a field in a tiddler (here the text field), you can use action-setfield, and not supply the usual $value parameter

Code

<$action-setfield $tiddler="MyJson" $index="A tiddler"/>

Result

Caution: This updates the actual tiddler. It does not simply return a string

{
    "Another tiddler": {
        "icon": "another-icon",
        "color": "#abcdef"
    }
}

More options are in the thread Delete JSON Object.

3 Likes

18 posts were split to a new topic: JSON Tiddlers and Ease of Use

JSON …

Very useful docs!

But should your post go under Tips & Tricks—so it doesn’t get lost in flow?

Small request …

Q: Could you prefix the tiddlers in the package with something like: “JSON-queries/”? Why? Helps keep it self-contained if imported into a user’s TW?

Just a thought!
TT

1 Like

Thank you Scott for the time you have tanke and this very detailed and useful answer with both key ideas and step by step examples covering all my use cases.

I think that the main idea to remember when dealing with json tiddlers (and that I was missing):

To manipulate json tiddlers, don’t directly alter the content of that tiddler. Create a new JSON string using a filter and jsonset operator then update the original

2 Likes

These sound like good ideas. I will look at both when I’m on a computer and not lying at bed at 4 am having already done Wordle* and my two other puzzles but still unable to get back to sleep.

I don’t know if I can change just my follow-up post to Tips & Tricks. But so long as @Eskha is okay with it, I can do it for the whole thread.

I didn’t write those tiddlers in order to post them. TiddlyWiki has simply gotten to be how I think. It’s how I organize my brain for many problems. When I was done but didn’t have time to write up my complete answer here, I added a brief one with those tiddlers to give the OP as timely a response as I could. Later I came back to give a proper response and decided others might like that approach too, so left them. But they certainly were not intended at first to act as reference docs, or I would have prefaced their titles as you suggest.



Wordle 1,610 4/6

:black_large_square::green_square::black_large_square::black_large_square::black_large_square:
:black_large_square::green_square::black_large_square::green_square::green_square:
:black_large_square::green_square::green_square::green_square::green_square:
:green_square::green_square::green_square::green_square::green_square:

2 Likes

Precisely. And if you simply want to fetch data, you don’t need that second step!

Right.

Nonetheless they are useful.

An additional extra Hutterite Mile could help US masses.

TT

Fine for me. I have turned the post inside a wiki.

1 Like

Hi folks, I did split the general discussion about JSON data tiddlers into its own thread, since the OP here was already marked as “solved”

See: JSON Tiddlers and Ease of Use

1 Like