Structure types returned by getstructurevalue(

getstructurevalue( is incredibly useful for accessing a JSON structure imported into a Panorama variable or field. However, the exact nature of the structure might not be known in advance, or it might be somewhat loose, for instance a dictionary might contain values each of which could be either a single text item or an array of text items. Thus, the value returned by getstructurevalue(jsonimport(Some_JSON_data)) might be of unknown type, and dictionaries, data arrays and simple variables eah need to be treated differently…

Looking for a function to find the type of data returned by a getstructurevalue( call, I first tried datatype(. This is intended to find the type of data held in a variable or field, so the first thing I realised was that it can only test data already held in a variable, rather than take a function as its argument. That’s not likely to be a problem very often because the result of getstructurevalue( would usually need to be stored somewhere anyway.

However, for both data arrays and dictionaries it returns the same data type, ‘Binary’. Fair enough I suppose in the general case, where a binary field might be used to store one of many data types: a dictionary or a data array, but also a rectangle, image files, etc. But not very helpful in this case.

As far as I can tell, importing JSON data into a Panorama variable or field could only result in a maximum of five data types — Integer, Float, Text, data array or dictionary — any of which might then be returned by getstructurevalue(. I’m guessing the quickest way to test a structure with Binary data type is to try accessing it as a data array and, if that gives an error, assume for this purpose it must be a dictionary instead. This is the best test function I can come up with to distinguish between them:

let Data=parameter(1)
let Type=datatype(Data) // argument must be a variable not parameter( function
if Type="Binary"
    Type=catcherror("Dictionary",array(Data,1))
    if Type<>"Dictionary"
        Type="Array"
    endif
endif
functionvalue Type

It’s no use in the general case when it might also be one of several more binary data types or just any old binary data loaded from a file, but it’s good enough for testing the types resulting from importing JSON data. This is what it returns:

1                           ==> "Integer"
1.1                         ==> "Float"
"1"                         ==> "Text"
dataarray(1)                ==> "Array"
jsonimport('[1]')           ==> "Array"
initializedictionary("A",1) ==> "Dictionary"
jsonimport('{"A":1}')       ==> "Dictionary"

Is there a better approach? And, although backward compatibility means the existing datatype( function must continue returning ‘Binary’ in all those cases, how hard would an alternative function be to distinguish not just the simple number and text data types but also as many of the possible binary types as possible? — obviously valid dictionaries and data arrays, but also bytes, words, longwords and longlongwords for sequences of 1/2/4/8 bytes, rectangles (if a 32-byte sequence can be proved to be a valid rectangle), etc., and only returning ‘Binary’ if a block of data can’t be proved to hold a valid Panorama data type.

I’m glad I’m not the only person to think so!! I have to agree that this is a very useful tool.

However, the exact nature of the structure might not be known in advance

That seems somewhat unlikely, usually JSON data formats are fixed and published in advance.

However, I like making Panorama as general purpose of a tool as possible. It might be cool to be able to make code in Panorama that could have random JSON thrown at it. So here you go:

Your code is basically exactly what I did for the new function, except that I wrote it in Objective-C. Also, I would recommend explicitly testing for Array, rather than assuming that anything that isn’t a dictionary is an array. Of course once the next version comes out it is moot, you can just use the new function. Also, I think your assumption is valid for data structions that have been imported from JSON.

Any 32 byte sequence is a valid rectangle. Of course many values would be somewhat nonsensical, but that doesn’t make them invalid. Since a 32 byte sequence could be most anything, I didn’t include this as a type the binarydatatype( function checks for.

Basically, the new function checks for bytes, words, longwords and long long words, and for values that are stored in Cocoa Objects (dictionaries, arrays and colors). For convenience, it also returns the data type of text and numbers (even though the function name is binarydatatype). You can read all about it in the documentation link above.

I hope you find something cool to do with this.

That is exactly the function I was searching for, thank you!