Read a Design Script Dictionary in a Zero Touch Node

I am attempting to read in information to Dynamo through a zero touch node with multiple outputs, and then use that information in my script. One of the outputs from the read node is a dictionary. At this moment, the read node is working beautifully, but my Zero Touch node that is supposed to read the dictionary output doesn’t work. I attempted to write a python node (something I’m more familiar with) to read the dictionary, and it won’t work. There’s something about the Design Script dictionary that doesn’t want to properly convert into a dictionary used by either of the two methods I’ve attempted to use. The input dictionary has Strings for keys and values of either type String or type List(Of String).

Using to create the Zero Touch node, I used roughly the following code, using objects for now to attempt to broaden my chance of success before narrowing down types to restrict input:

Public Shared Function GetCategoryValues(ByVal category As Object, ByVal name as Object) As Object
    Return category.Item(name.ToString())
End Function

This function is supposed to retrieve one value by the key, or name input, of the node. The warning I receive from this attempt is:

Warning: Object must implement IConvertible.

This warning occurs no matter how broad or restrictive I attempt to make the type of either inputs or the output.

For the Python node attempt at reading the dictionary, I get a myriad of issues depending on how I attempt to read or convert the input to a python dict, but the most common warning I received was:

AttributeError: ‘Dictionary’ object has no attribute ‘keys’

Now I don’t know about you all, but I understand dictionaries to have both keys and values, neither of which apparently a member or “attribute” of this particular dictionary. The syntax I most recently attempted with Python was simply:

OUT = IN[0][str(IN[0])]

I should note, the dictionary is originally being generated from a Zero Touch node, using the <MultiReturn({“out1”,“out2”})> approach, and I am using Revit 2019.2, Dynamo 2.0.3. The dictionary nodes of OOTB Dynamo read the dictionary output of my node perfectly fine, with no issue, but I want the ability to control both this GetValue node and other nodes in my script with a single Category node, such that Category: Doors would be converted to a string inside my GetValue node and then used as a key, instead of having an OOTB node with a Code Block node containing "Doors";.

Any help on this very confusing and frustrating matter would be greatly appreciated!

I should note, since I didn’t catch it in time to edit the post, the python syntax I used was actually:

OUT = IN[0][str(IN[1])]

And upon attempting to run the Python node today, the warning I received using the above syntax is:

TypeError: 'Dictionary' object is unsubscriptable.

I am apparently unfamiliar with either how to handle DesignScript dictionaries in Python and, or how to generate the dictionary in such a way that it is in a readily readable state for both Design Script and Python/Zero Touch nodes.

I am having a difficult time finding documentation on DS dictionaries, but the first thing I would try is the dir() function to see what methods/properties are available. You may have to reconstruct the incoming Dictionary object as a Python dict (if there isn’t any nesting). You can use OOTB Dictionary.Keys and Dictionary.Values nodes, pass them as inputs to your Python node, and do something like this:

keys = IN[0]
values = IN[1]
py_dict = dict(zip(keys, values))

I would just return regular .net or python dictionaries, they should be converted back and forth - checkout the python marshaller.

You have to keep in mind you are dealing with potentially three dictionaries -
DS dictionaries (which are defined in c#)
iron python dictionaries
c# system.Dictionary type.

input marshaller for python

output marshaller for python:

I would just use an IDictionary on whatever function are you writing in c# or is that

just for reference, here is the dynamo dictionary type:

I attempted to do that, as well as use other methods/properties I’m familiar with using, but no matter what I tried to use to access the actual input dictionary, it wouldn’t work. It seems like (and I may be wrong due to my own unfamiliarity with DS dictionaries and how they interact with Python node inputs) Python is incapable of access DS dictionary methods or properties, at least without some kind of conversion I’m unaware of. This may also just be a version issue, but at the moment I’m restricted to the version of Dynamo.

I considered doing the second route you suggested before posting here, too, but I’m trying to avoid adding too many nodes into my script if I can avoid it. I’m currently in the process of optimizing it and reducing the nodes due to its size. It’s gotten a little laggy to navigate, though it does process fairly quickly, respective to the Revit model size.

I am writing in due to my familiarity and readability of the code making more sense to me, but there’s not really a difference in terms of .NET, so I can usually translate pretty easily back and forth.

For whatever reason, I never tried setting my input to IDictionary, just everything except that, but that worked. It’s now reading the DS Dictionary perfectly fine. Thanks for the fix!

As reference, my VB function now reads:

Public Shared Function GetCategoryValues(ByVal category As IDictionary, ByVal name as Object) As Object
    Return category.Item(name.ToString())
End Function

I am still currently utilizing Object here because of the ability to use either Category or String inputs, and the output is entirely dependent on what the originating Dictionary is, but will eventually go back through and revise that for overrides instead.