Skip to main content
July 11, 2022
Solved

Casting from JSON to Dictionary to CDT, array entries are null

  • July 11, 2022
  • 7 replies
  • 0 views

I have a REST service that returns JSON which is converted to Dictionary by the integration.  I have CDTs I have imported from the service WSDL (so the property names exactly match the JSON names).  The problem is that array properties are left null instead of being populated.

I'm trying to convert it this way.... with a single call to cast of the top-level node.

  /*local!rawData: rule!SH_GetLibraryIntegration(libraryName: ri!libraryName) */
  local!rawData: a!fromJson(
    "{""GetLibraryResult"":{""Name"":""Uptown Public Library"",""HeadLibrarian"":""Kathlyn Walton"",""Books"":[{""Author"":""Fyodor Dostoevsky"",""Title"":""Crime and Punishment"",""IsCheckedOut"":false,""DueDate"":null},{""Author"":""Charles Dickens"",""Title"":""A Tale of Two Cities"",""IsCheckedOut"":true,""DueDate"":""01-10-2021""}]}}"
  ),
  fn!cast(
    'type!{http://schemas.datacontract.org/2004/07/TestService}Library',
    local!rawData.GetLibraryResult
  )

However, The "books" (in my example) are null and did not make it into the CDT.

I found a way to do this by converting the dictionary to individual maps, property by property, and then to a CDT.  However, this is really ugly and tedious.  

  /*local!rawData: rule!SH_GetLibraryIntegration(libraryName: ri!libraryName) */
  local!rawData: a!fromJson(
    "{""GetLibraryResult"":{""Name"":""Uptown Public Library"",""HeadLibrarian"":""Kathlyn Walton"",""Books"":[{""Author"":""Fyodor Dostoevsky"",""Title"":""Crime and Punishment"",""IsCheckedOut"":false,""DueDate"":null},{""Author"":""Charles Dickens"",""Title"":""A Tale of Two Cities"",""IsCheckedOut"":true,""DueDate"":""01-10-2021""}]}}"
  ),
  fn!cast(
    'type!{http://schemas.datacontract.org/2004/07/TestService}Library',
    a!map(
      Books: fn!cast(
        'type!{http://schemas.datacontract.org/2004/07/TestService}ArrayOfBook',
        a!map(
          Book: a!forEach(
            items: local!rawData.GetLibraryResult.Books,
            expression: fn!cast(
              'type!{http://schemas.datacontract.org/2004/07/TestService}Book',
              fv!item
            )
          )
        ) 
      ),
      Name: local!rawData.GetLibraryResult.Name,
      HeadLibrarian: local!rawData.GetLibraryResult.HeadLibrarian,
    )
  )

My real service has a very large JSON object (300+ classes in the web service) and many, many array-based properties.  This will be exceedingly tedious and error prone to convert to a CDT through map-cast method above.

Is there a better way to do this conversion?

Best answer by stefanhelzle0001

In Appian CDTs, you would make the field "books" in the top-level CDT of type "Book" and a multiple. This will then cast perfectly from/to JSON. The in-between CDT is not necessary.

7 replies

andrewh6762
July 12, 2022

I've made my own CDTs and the casting works. Maybe there's an issue with the CDT? I used your exact local!rawData JSON string you provided above.

stefanhelzle0001
Brainy
July 12, 2022

Can you post a screenshot of the CDT configuration?

July 12, 2022

Here are the CDTs.  These were imported from a DotNet web service's WSDL.

Here is a fragment from the WSDL that defines these.

		
			
				
					
					
					
				
			
			
			
				
					
				
			
			
			
				
					
					
					
					
				
			
			
		

stefanhelzle0001
Brainy
July 12, 2022

Hm ... this seems a bit weird. Why is there a books field which is of a type that has only one field "book" which is a list of books.

I understand that the provided JSON does not cast to this structure.

To understand what is going on, create a data structure using the CDT types and turn that into JSON to spot the difference.