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?
Discussion posts and replies are publicly visible
Can you post a screenshot of the CDT configuration?
Here are the CDTs. These were imported from a DotNet web service's WSDL.
Here is a fragment from the WSDL that defines these.
<xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/TestService" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.datacontract.org/2004/07/TestService"> <xs:complexType name="Library"> <xs:sequence> <xs:element minOccurs="0" name="Books" nillable="true" type="tns:ArrayOfBook"/> <xs:element minOccurs="0" name="HeadLibrarian" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="Name" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:element name="Library" nillable="true" type="tns:Library"/> <xs:complexType name="ArrayOfBook"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="Book" nillable="true" type="tns:Book"/> </xs:sequence> </xs:complexType> <xs:element name="ArrayOfBook" nillable="true" type="tns:ArrayOfBook"/> <xs:complexType name="Book"> <xs:sequence> <xs:element minOccurs="0" name="Author" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="DueDate" nillable="true" type="xs:dateTime"/> <xs:element minOccurs="0" name="IsCheckedOut" type="xs:boolean"/> <xs:element minOccurs="0" name="Title" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:element name="Book" nillable="true" type="tns:Book"/> </xs:schema>
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.
This is apparently how DotNet handles defining list/array-based properties in the WSDL.
Here's the service class in C#
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.
The CDTs were built from the WSDL.... so it is a matter of getting DotNet to build the WSDL in a way that is compatible with Appian. I will see what I can do for this.
Thank you.