condition to check if type is a CDT

Certified Associate Developer

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

Parents Reply Children
  • 0
    Certified Associate Developer
    in reply to Stefan Helzle

    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"
    ),

    )

  • 0
    Certified Lead Developer
    in reply to erikb0001

    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.

  • 0
    Certified Associate Developer
    in reply to Stefan Helzle

    Hello Stefan,

    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,

    Erik

  • 0
    Certified Lead Developer
    in reply to erikb0001

    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?

  • 0
    Certified Associate Developer
    in reply to Stefan Helzle

    Certainly helps, thanks for your answer Stefan.

  • 0
    Certified Lead Developer
    in reply to erikb0001

    You are welcome. In case you need support in your solution design, we can get into contact outside this forum.

  • 0
    Certified Associate Developer
    in reply to Stefan Helzle

    Hello Stefan,

    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?

    Kind Regards,

    Erik


     

  • 0
    Certified Lead Developer
    in reply to erikb0001

    You create a dictionary not via type but via {} or map(). See docs.appian.com/.../Expressions.html

  • 0
    Appian Employee
    in reply to erikb0001

    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")
    }

  • 0
    Certified Associate Developer
    in reply to Stefan Helzle

    thank you, makes sense.