Hello community,
I wonder if it is possible to check with in a if condition if a passed value of any type is a CDT.I want to make a generic expression rule to convert a body from JSON to CDT with two rule inputs.1 body of type text.2 any type, but only CDT's so no integer, string etc.
So I want the to JSON function only to execute when the ruleinput is a CDT, if not I want to return a custom error message text string.Are the CDT in a specific reserved numeric range so I can use that, or is there another approach?
Kind Regard,
Erik
Discussion posts and replies are publicly visible
I think there are two types you need to consider. Dictionary and Map. The types are
'type!{www.appian.com/.../2009}Dictionary'
'type!{http://www.appian.com/ae/types/2009}Map'
You can use them to compare to "runtimetypeof(ri!YOUR_RULE_INUT)"
Thank you Stefan,
Maybe it's my environment, or I misunderstood your answer.
I am not able to find the types you mention to compare.It I type: 'type!{www.appian.com/.../2009}Dictionary' or 'type!{http://www.appian.com/ae/types/2009}Map' in the if expression.It seems that I can only access CDT's in the system.Kind Regards,
These are not auto-completed. Your code would look like
if( or( runtimetypeof(ri!YOUR_RULE_INPUT) = 'type!{http://www.appian.com/ae/types/2009}Dictionary', runtimetypeof(ri!YOUR_RULE_INPUT) = 'type!{http://www.appian.com/ae/types/2009}Map' ), __THIS__, __THAT__ )
Hello Stefan,
Thanks for the example Stefan.The result of the expression is false when I use code below and pass it a CDT:
a!localVariables( local!typeCDT: typeof(ri!input), if( or( runtimetypeof(ri!input) = 'type!{www.appian.com/.../2009}Dictionary', runtimetypeof(ri!input) = 'type!{www.appian.com/.../2009}Map' ), cast(local!typeCDT, a!fromJson(ri!jsonBody)), "false" ), )
Got it. I was a bit on a wrong path here.
I do not know of a way of how to check whether a value is a CDT in general.
What do you want to achieve in general?
When I do serious integrations, I create an expression fetching the data from a specific endpoint so I know which structure to expect. In case the API is stable, I just make the integration object to return a dictionary and not the JSON string. Then I cast it to the type I expect.
In case the API is not stable, I make the integration to return the JSON string and use a plugin to validate whether it is valid JSON. Then turn it into a dictionary and cast it.
The API is stable and the structure of the payload matches the CDT.As it is good practice to reuse code by making it dynamic I created a expression rule with inputs: any type for the CDT, and jsonBody type text.
It works fine as long as CDT's are being passed.
In case of on error there is of course error handling in the api and will send the configured error response.
So it's not crucial for functionality but as a starter with Appian I am exploring it's functionality's.
There is no known logic about the way Appian handles type numbers so a range of numbers reserved for Appian build in types and a range for custom defined types. then I could make a condition like typenumber>x, where x is the begin nr of not system reserved types.
Sub. question, is it possible to use a Appian error message in a condition, so if error = x, then ...?
Thanks for your help.
Kind Regards,
OK. Reusing code is a good idea, but should be avoided for some situations. Reusing code mostly means to add another level of abstraction in top of something. Abstraction always means to implement certain assumptions. And your assumptions might be different from other peoples assumptions.
Regarding type numbers in Appian. Appian is written in Java and all internal type have a specific number which AFAIK is below 1000. But this is nothing you should rely on as this is internal non-public implementation details.
When I fetch data from any external system, I try to put the logic into an expression which is consistent in its returned data type. If I use that in a place where my logic cannot work without a proper value I use the error() function to stop whatever is going on. In a process the error() function would stop execution.
I see a lot of people new to Appian trying to think in the way they are used to in terms of solution design. This often leads to unnecessary complex designs. In Appian most things are just not complicated to implement and a non-issue compared to other programming environments.
Does this help?
Certainly helps, thanks for your answer Stefan.
You are welcome. In case you need support in your solution design, we can get into contact outside this forum.
One more question regarding the dictionary datatype.I tried to declare a variable with type constructor dictionary based on url namespace you provide.It trows an error:
if I use 'type!{http://www.appian.com/ae/types/2009}Dictionary',
like this: local!Dict1: 'type!{http://www.appian.com/ae/types/2009}Dictionary',error: expression evaluation error at function local!Dict1 [line 12]: Invalid type for type constructor: Dictionary
Could this have something to do with the environment I am working in?
You create a dictionary not via type but via {} or map(). See docs.appian.com/.../Expressions.html
Like Stefan said, I don't believe you can define a dictionary using a type constructor - usually the easiest way is to just define an array and add any keys you want to use, which will automatically define a dictionary. Here's an example:
{ {id: 1, text: "One"}, {id: 2, text: "Two"}, {id: 3, text: "Three"} }
That being said, if you plan to construct the data yourself, I highly recommend using a map instead of a dictionary. Maps provide the same flexibility of dictionaries in that you can define any keys you want to use, but a key difference between maps and dictionaries is that maps are strongly typed. If you use a dictionary, you will see all the fields show up as a type "Variant", which means they can be anything. If you use a map though, the types will show as "Text", "Integer", etc. This makes it much easier to use the data in a map. You can construct a map with a similar syntax, just use a!map() instead of the brackets:
{ a!map(id: 1, text: "One"), a!map(id: 2, text: "Two"), a!map(id: 3, text: "Three") }
Thank you Peter, I will keep in mind to use maps instead of directory when the datatypes of the fields matter(or just use maps in general instead of dictionary.
After restarting my computer and installing the computer monitoring software, the settings are out of order, I want to return a custom error message text string.Is CDT in a certain reserved numeric range for me to use, or is there a different approach?