RFC: Web component and dictionaries

This block looks to be missing sockets …
walk%20at%20all%20level%20missing%20sockets

The Web JSONTextDecode block tool tip needs updating for dictionaries,
JSONTextDecode%20tool%20tip%20needs%20update%20for%20dictionaries

Actually, the block is correct. It is used as part of the list by walking key path block to iterate over every item at a given point in the tree rather than selecting a specific branch. I considered using a special string, such as "*" to match all, but on the off chance that someone might use that as a key I decided have a special block representing a constant value that could never be a key in the JSON object would be best. It also opens things up so that in the future we can also allow for anonymous procedures as filters to select some subset of the tree to explore.

Yes, the out-of-date tooltip is my fault. I mostly want to get feedback on how the dictionary-based functionality is working while I finish up the documentation. Note that there is a documentation page for all of the dictionary blocks (accessed via Help on the context menu), so any feedback you have on the contents of that page would be helpful. At the very least I'm going to provide a more detailed explanation of the blocks used for walking an object tree built from dictionaries and lists.

When i press the gear on the dictionary blocks i get some strange effects.

Selection_999(880)

I don’t think there should be a gear in the above block.

I also see strange gears popping up in the create empty list block and not working gears in other blocks.

That's my fault from when I was renaming some of the messages. I'll be pushing a fix up shortly.

1 Like

The fix has been pushed. I’ve also set up the build server if you’d like to try and build apps with the dictionaries. As usual, the companion is available via the dialog at Help > Companion Information.

Edit: I’ve identified another bug in the mutator. For the most part things should be working okay unless you attempt to reorder the pairs using the mutator. I’m looking into it now.

This block looks like a free floating ELSE block (shudder)…

It has no meaning outside of a parent block,
so it should come in mutably via the new parent block,
list by walking all at current level (dictionary) (admittedly verbose name)
with child blocks in the mutator:
key path
transforming it into
list by walking (key path, dictionary)

Alternatively, keep the key path default but have the mutator
offer the ALL (*) value only in the key path context.

I would also suggest giving some thought to making the
key path more explicit by extending the mutator functionality
to allow step by step addition of key path steps in the mutator,
like the way an IF/THEN/ELSEIF/ELSEIF ladder can be extended.

A super deluxe implementation of this block
would pull in a sample JSON file at design time
and pre-populate the mutator with aptly named
path steps.

The blue dictionary block color might present problems contrasting with the blue
mutator block.

The new dictionary blocks don’t seem to have context menu items. The
context menu that opens on the get values block (for example)
is the workspace context menu, with options to delete all blocks, etc.

This is an oversight, I assume?

Get Values block Considered Harmful
get%20values%20considered%20harmful

I can’t think of any use for this block, except mischief and confusion.

The TinyDB GetTags block is a mainstay, but I have never seen a request for
a TinyDB GetValues block.

I would sooner rip the labels off all the cans in my pantry and
play “Guess the Dog Food”.

Eh, we do this as well with the break block for looping constructs. We can certainly add an error check, but my vision was that people could store and manipulate paths as lists in a very LISP-y way. A future update will probably add the ability to include procedures as inputs to the path for applying filtering operations, for example, and this is a shortcut block to a (lambda (x) #t) filter. I'm not sure I like the idea of tying it to a mutator because ultimately that means it's tied to the block and you can't manipulate it in any way at runtime. It's just as well that one could implement this block (well, the list by walking dictionary) block by a series of procedures, but the idea that we can take a technically challenging functional composition and reduce it to a single block like this is incredibly powerful.

Hmm. I just checked this and confirmed what you're experiencing. I only see this for the get keys and get values blocks. It's enough to go on to put together a fix. Thanks for the report.

Any situation where you have ids mapping to entities in a lookup table, such as a user table (user id - user object), blog posts (post id - post data), etc. for starters.

Yes, certainly one could use the GetTags block and then iterate over the list of tags getting the corresponding values. However, this requires more blocks and is slower (especially for TinyDB since each operation accesses the file system). Just because you can do it one way, doesn't mean there isn't a more elegant way that makes sense for some applications (and maybe not yours, which is fine).

Most languages that provide a hash table-like object (maps, dictionaries, etc.) tend to have both key and value iterators. In fact, this block is implemented by iterating over the collection returned by Java Map's values() operator and returning them in a list. The overhead is so little it wouldn't make much sense to not provide it (especially considering the alternative of implementing the exact same logic in blocks).

I'm a cat owner personally, but this has never occurred to me as something I can or should try. Is this a common activity among people who own dogs? :grinning:

Regarding the values(dictionary) block, is there a guarantee of ordering in the result?
Does that ordering match the ordering of the **keys(dictionary) ** block?

Mind you, JSON does not guarantee the ordering of
keys:

JSON parsing libraries have been observed to differ as to whether or
not they make the ordering of object members visible to calling
software. Implementations whose behavior does not depend on member
ordering will be interoperable in the sense that they will not be
affected by these differences.

I am anticipating the first board request from some one who wants to show keys and values in two parallel ListView columns.

Perhaps these domain specialists can impress upon you the
dangers of disassociating values from containers …
https://www.google.com/search?q=youtube+3+stooges+coffee+painting

TypeBlocking is a dictionary shows
is a dictionary %1
on the selection list. None of the other is-a family
come up like this, with a %1 added.
The resultant block looks okay, though.

Yes, this is guaranteed to be the case unless you perform a remove operation between the two calls. The dictionary is implemented using Java LinkedHashMap, which preserves the order in which the pairs are added to the map. This was chosen specifically because we wanted to allow for interoperability with associative lists, and so if you pass a dictionary into lookup in pairs, or into a for-each-item-in-list block, it will iterate over the dictionary in exactly the same order as the corresponding list of lists representation.

We do sort JSON keys alphabetically when parsing a dictionary, which is also consistent with a number of JSON libraries albeit left unspecified by the spec.

I'm trying one of the newer Blockly features here that allows us to interpolate strings to simplify the block descriptions and make them easier to internationalize. Unfortunately, typeblock is also interacting with it a bit weirdly, but I think it shouldn't be too difficult to fix.

I’ve encountered a functionality shortfall.

I’ve done a JSONDecode on this JSON
forecastlong.txt (14.2 KB)
using this browser app, recently extended to accept dictionaries, lists, and scalars
out of the Web JSONDecode block:
browse_JSON_V3.aia (13.3 KB)

and followed the top level dictionary key list
hoping to get the list value it had.
Unfortunately, the JSON decoding seems to have stopped dead
at this branch, refusing to decode the list markup.

So what are supposed to do when we want to decode a mixed
JSON object/list/object sandwich?

This has been fixed.

This was a sanitization failure on our part. We were passing back lists as an internal Java type rather than the user facing list type. I've updated the companion and build server to fix this issue.

The mixed object/list/object JSON sandwich conversion fail has been fixed.

I added a test of the list by walking key path block to show the
result of following the path from the root of the decoded JSON,
and started to get crashes trying to interpret the new block’s output as a list …

browse_JSON_V4.aia (15.3 KB)

Intermediate results applying the list by walking key path block …

list%20or%20not%20a%20list Show%20Lists%20As%20JSON%20Off

Observations:

The Do It facility shows dictionaries as JSON , though the Screen1 ShowListsAsJSON flag is off - okay, I guess

Bug:

The Do It result for the output of the list by walking key path block is not showing a list, as expected by the AI2 list blocks. Notice the square brackets on the Do It output, as opposed the the round brackets on the global path variable Do It bubble.
My attempt at sending the supposed list output into a csv row from list hung at run time.

This error happens when resetting connection to the Companion:
notes = Browser: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36
foundIn = v179-41-g7ed6f1e74
faultData = com.google.gwt.core.client.JavaScriptException: (AssertionError) : Assertion failed: Expecting tuple from value block “dictionaries_walk_tree”.
projectId = 5701325169885184

This started after adding the block to walk a key path in a dictionary.

I've pushed a new version. This was another place where we were sending back an internal Java object rather than the blocks-equivalent. Unfortunately, I've been editing with ShowListsAsJSON set to true, which makes them pretty indistinguishable from one another so I didn't catch that.

This is a bug in the code generation for that block that I have now fixed.

The test site has been update with a new companion.