Create JSON file format from AX 2012 X++

 To create JSON file format we need to create some contract classes for the parameters that we are using in File and we need to populate data into it.

Now lets create some contract classes for required parameters. I have provide one class for the example

1. Example :  Shipment contract 

[DataContractAttribute]

class E2C_APIShipmentContract

{

    str 50 shipment_reference;

    str 50 customer_reference_1;

    str 50 customer_reference_2;

    str movement;

    str authorisationNumber;

    boolean email_tracking_enabled;

        List items ;//= new List(Types::Class);

}

Add some ParmMethods to it

 [DataMemberAttribute]

    public str shipment_reference(str _shipment_reference = shipment_reference)

    {

        shipment_reference = _shipment_reference;

        return shipment_reference;

    }

[DataMemberAttribute]

    public List items(List _items = items)

    {

        items = _items;

        return items;

    }

[DataMemberAttribute]

    public str customer_reference_1(str _customer_reference_1 = customer_reference_1)

    {

        customer_reference_1 = _customer_reference_1;

        return customer_reference_1;

    }

So on.....

One Main Contract

[DataContractAttribute]

class E2C_APIMainContract

{

    str 50 order_reference;

    str 50 payment_method;

    List shipments ;//= new List(Types::Class);//todo

}

[DataMemberAttribute]

    public List shipments(List _shipments = shipments)

    {

        shipments = _shipments;

        return shipments;

    }

[DataMemberAttribute]

    public str payment_method(str _payment_method = payment_method)

    {

        payment_method = _payment_method;

        return payment_method;

    }

[DataMemberAttribute]
    public str order_reference(str _order_reference = order_reference)
    {
        order_reference = _order_reference;
        return order_reference;
    }


Now Create one class to populate the data into this parameters.

/// <summary>

///  Populating API input etc.

/// </summary>

/// <remarks>

///  run method of class

/// </remarks>


public void run()

{

    StarTrackDispatchLog        dispatchLog;

    APIMainContract             mainContract;

    APIFromContract             fromContract;

    APIAttributesContract       attributesContract;

    APIToContract               toContract;

    APIShipmentContract         shipmentContract;

    APITransitCoverContract     transitCoverContract;

    APIFeaturesContract         featuresContract;

    E2C_APIItemContract             itemContract;

    List            shipmentLineList = new List(Types::Class);

    InventShipmentTableASL          shipmentTable;

    InventShipmentPalletASL         shipmentPallet;

    InventPalletTableASL            palletTable;

    InventCartonLinesASL            cartonline;

    str                              jsonVal,resonseVal;

    List                            mainJsonList,shipmentList,fromList,tolist,itemList;

    LogisticsPostalAddress          LogisticsPostalAddress;

    CustTable                       custTable;

    LogisticsLocation               location;

    SalesTable                      salestable;

    LogisticsElectronicAddress      logisticsElectronicAddress;

    str                              phone,email,voulumeStr,weightStr,cubicStr;

    DirPartyTable                   dirpartyTable;

    str                              errorMsg;

    Counter                         countConsignment;

    str                              articleId;//  Added on 12/10/2021

    E2C_APITrackingContract         trackingContract;//added on 15/10/2021

    InventCartonConsignmentIdASL    newConsignment;

    SalesDeliveryAllocationTableASL salesDeliveryAllocationTableASL;

    InventParameters                inventParameters = InventParameters::find();

    //InventCartonTableASL            inventCartonTableASL;

   /* #define.product_id('EXP')

    #define.packaging_typeCTN('CTN')

    #define.packaging_typePAL('PAL')

    #define.Attn('Attn : Mr. Ezekiel')

    #define.FromName('Easy2C Pty Ltd C/o WorldwideDistribution')

    #define.AddrLine('Attn:Mr. Ezekiel,92-100 Belmore Road')

    #define.suburb('Riverwood')

    #define.state('NSW')

    #define.postcode('2210')

    #define.Phone('1800882216')*/



    shipmentTable = InventShipmentTableASL::find(shipmentId);


    mainContract = new E2C_APIMainContract();

    mainContract.order_reference(shipmentId) ;

    mainContract.payment_method('CHARGE_TO_ACCOUNT');


    shipmentList = new List(Types::Class);


   while select shipmentPallet

       where shipmentPallet.ShipmentId == shipmentTable.ShipmentId

    {

        palletTable = InventPalletTableASL::find(shipmentPallet.PalletId);

        countConsignment = 0;

        newConsignment = "";

        cartonline.clear();

        cartonline = null;

        while select cartonline

            order by ConsignmentId

            where cartonline.PalletId == palletTable.PalletId

        {


            if(newConsignment != cartonline.ConsignmentId)

            {

                newConsignment = cartonline.ConsignmentId;

                countConsignment = 0;

            }


            countConsignment++;


            shipmentContract = new  APIShipmentContract();

            fromContract    = new APIFromContract();

            featuresContract = new APIFeaturesContract();

            transitCoverContract = new APITransitCoverContract();

            attributesContract = new APIAttributesContract();

            toContract      = new APIToContract();

            trackingContract = new APITrackingContract();// 


            itemList = new List(Types::Class);

            //palletTable = InventPalletTableASL::find(shipmentPallet.PalletId);

            custTable = CustTable::find(cartonline.custAccount());


            shipmentContract.shipment_reference(shipmentId);

            shipmentContract.customer_reference_1();

            shipmentContract.customer_reference_2();

            shipmentContract.email_tracking_enabled(false);

            //Ns- Added by UXVX

            shipmentContract.movementType(inventParameters.E2C_MovementType);

            shipmentContract.authorisationNumber(shipmentId);

            //NE-ended by Vijay


            //fromContract.name(#FromName);


            fromList = new list(Types::String);

            dirpartyTable = DirPartyTable::findRec(custtable.Party);

            email = dirpartyTable.primaryEmail();


           /* fromlist.addEnd(#AddrLine);

            fromContract.lines(fromlist);

            fromContract.name(#FromName);

            fromContract.suburb(#suburb);

            fromContract.state(#state);

            fromContract.postcode(#postcode);

            fromContract.phone(#Phone);*/

            // NS- added by UXVX -29-03-22

            if (this.getShipingFrmState(cartonline) == 'WA')

            {

                fromlist.addEnd(inventParameters.APIAddrLine);

                fromContract.lines(fromlist);

                fromContract.name(inventParameters.APIFromName_WA);

                fromContract.suburb(inventParameters.APISuburb_WA);

                fromContract.state(inventParameters.APIStateId_WA);

                fromContract.postcode(inventParameters.APIPostCode_WA);

                fromContract.phone(inventParameters.APIPhone_WA);

            }

            else

            {

                fromlist.addEnd(inventParameters.APIAddrLine);

                fromContract.lines(fromlist);

                fromContract.name(inventParameters.APIFromName);

                fromContract.suburb(inventParameters.APISuburb);

                fromContract.state(inventParameters.APIStateId);

                fromContract.postcode(inventParameters.APIPostCode);

                fromContract.phone(inventParameters.APIPhone);

            }

            //NE - ended by UXVX on 29-03-22


            itemContract    = new E2C_APIItemContract();


            LogisticsPostalAddress = null;

            location = null;

            salestable = cartonline.salesTable();

            //LogisticsPostalAddress = salestable.deliveryAddress();

            shipmentContract.fr(fromContract);

            //****

            salesDeliveryAllocationTableASL = cartonline.salesDeliveryAllocationTable();

            LogisticsPostalAddress = this.postalAddress(cartonline);


            toContract.name(salesDeliveryAllocationTableASL.LocationDescription);

            toContract.business_name();

            toContract.suburb(salesDeliveryAllocationTableASL.County);

            toContract.state(salesDeliveryAllocationTableASL.State);

            toContract.postcode(LogisticsPostalAddress.ZipCode);

            toContract.phone(phone);


            tolist = new List(Types::String);

            if(strLen(LogisticsPostalAddress.Street) >40)

            {

                tolist.addEnd(strLFix(strReplace(LogisticsPostalAddress.Street,"\n"," "),40));

            }

            else

            {

                tolist.addEnd(strReplace(LogisticsPostalAddress.Street,"\n"," ")) ;

            }

            toContract.lines(toList);



            shipmentContract.to(toContract);

            itemContract.allow_partial_delivery(true);

            itemContract.authority_to_leave(false);

            //itemContract.consignment_id(cartonline.ConsignmentId);

             //added on 15/10/2021

            articleId = "";

            articleId = this.getArticleId(cartonline,countConsignment);


            trackingContract.consignment_id(cartonline.ConsignmentId);

            trackingContract.article_id(articleId);//  Added on 12/10/2021

            trackingContract.barcode_id(articleId);//  Added on 12/10/2021


            //ended on 15/10/2021

            //heightstr = strFmt("%1",real2int(cartonline.CartonVolume*100));

            //itemContract.height(heightstr);


            //itemContract.length(heightstr);

            if(cartonline.CartonWeight > 40)

            {

                //itemContract.packaging_type(#packaging_typePAL);

                itemContract.packaging_type(inventParameters.E2C_APIPackTypePAL);

            }

            else

            {

              //itemContract.packaging_type(#packaging_typeCTN);

               itemContract.packaging_type(inventParameters.E2C_APIPackTypeCTN);

            }


            //itemContract.packaging_type(#packaging_type);

            //itemContract.product_id(#product_id);

            itemContract.product_id(inventParameters.E2C_APIProductId);

            weightStr = strFmt("%1",cartonline.CartonWeight);

            itemContract.weight(weightStr);

           // itemContract.width(heightstr);

            cubicStr = strFmt("%1",decRound(cartonline.CartonVolume,3));

            itemContract.cubic_volume(cubicStr);

           // if(Counter ==1)

           // {

                attributesContract.cover_amount(0);


                transitCoverContract.attributes(attributesContract);

                featuresContract.TRANSIT_COVER(transitCoverContract);

                itemContract.features(featuresContract);

               itemContract.tracking_details(trackingContract);//added on 15/10/2021

           // }

           itemList.addEnd(itemContract);

             shipmentContract.items(itemList);

             shipmentList.addEnd(shipmentContract);



        }


    }

Add all the contracts to one main contract

    mainContract.shipments(shipmentList);

    jsonVal = FormJsonSerializer::serializeClass(mainContract);

    try

    {

        resonseVal = this.makePOST(jsonVal);

        info("Dispatch shipment sucessfully");

    }

    catch

    {

        resonseVal = "Dispatch shipment failed. Please try.";

        error(resonseVal);


    }



    dispatchLog.ShipmentId = shipmentTable.ShipmentId;

    dispatchLog.APIRequest = jsonVal;

    dispatchLog.APIResponse = resonseVal;

    dispatchLog.DateTime = DateTimeUtil::utcNow(); //DateTimeUtil::applyTimeZoneOffset(DateTimeUtil::utcNow(),DateTimeUtil::getClientMachineTimeZone());

    dispatchLog.insert();

    //Dispatch shipment sucessfull.

    //Dispatch shipment failed. Please retry.

}

public static void Main(Args _args)

{

    E2C_AutoPostAPI    autoPostAPI = new E2C_AutoPostAPI();

    if(_args.caller())

    {

        autoPostAPI.parmShipmentId(_args.parm());

        autoPostAPI.run();

    }

}

/// <summary>

/// Post API Request

/// </summary>

/// <param name="_requestContent">

///  request content

/// </param>

/// <returns>

///  API response

/// </returns>

/// <remarks>

///  Method is used to handle API request and response

/// </remarks>


public str makePOST(str _requestContent)

{

    System.IO.Stream dataStream;

    System.Net.WebResponse response;

    str wsResponse;

    System.IO.StreamReader reader;

    System.IO.StreamReader streamReader;

    InventParameters        inventParameters = InventParameters::find();

    str url = inventParameters.APIUrl; //URL

    str user = inventParameters.APIKeyUsername; ; //Key User Name

    str pass = inventParameters.APIPwd;;// Password

    str _accountNum = inventParameters.APIAccountNum; ; //Accountnum

    System.String headerAccValue;

    System.String headerAccKey = "account-number";

    System.String postData;

    System.Byte[] byteArray;

    System.Text.Encoding encoding = System.Text.Encoding::get_UTF8();

    System.Byte[] bytes = encoding.GetBytes(user + ":" + pass);

    System.String base64 = System.Convert::ToBase64String(bytes);

    System.String basic = "Basic ";


    System.String headerKey = "Authorization";

    System.String headerValue = System.String::Concat(basic,base64);

    System.Net.WebRequest request = System.Net.WebRequest::Create(url);

    System.Net.WebHeaderCollection headers = request.get_Headers();//Headers;

    headers.Add(headerKey,headerValue);



    headerAccValue = _accountNum;

    headers.Add(headerAccKey,headerAccValue);

    postData = _requestContent;

    byteArray = encoding.GetBytes(postData);

    // Set the ContentType property of the WebRequest.

    request.set_ContentType("application/json");

    // Set the ContentsLength property of the WebRequest.


    request.set_ContentLength( byteArray.get_Length());

    request.set_Method("POST");

    // Get the request stream.

    dataStream = request.GetRequestStream();


    // Write the data to the request stream.

    dataStream.Write(byteArray, 0,  byteArray.get_Length());


    // Close the Stream object.

    dataStream.Close();


    response = request.GetResponse();

    reader = new System.IO.StreamReader(

    response.GetResponseStream());

    wsResponse = reader.ReadToEnd();



    return wsResponse;

}

Create Json Serilizer class

class E2C_FormJsonSerializer

{

    System.IO.StringWriter stringWriter;


     Newtonsoft.Json.JsonTextWriter jsonWriter;


    str nullPlaceholder;


    utcDateTime dateTimeBase;


    Map theDataContractClass;


    MapEnumerator theDataContractClassEnumerator;

}

public void flushCache()


{


   theDataContractClass = null;


}

private str json()

{

   str json;

  json = stringWriter.ToString();

   json = strReplace(json, strFmt('"%1"', nullPlaceholder), 'null');

   return json;

}

private void new()

{

  stringWriter = new System.IO.StringWriter();

   jsonWriter = new Newtonsoft.Json.JsonTextWriter(stringWriter);

   nullPlaceholder = guid2str(newGuid());

   dateTimeBase = FormJsonSerializer::dateTimeBase();

}

private void serializeArray(Array _array)

{

   Types arrayItemType;

  int arrayIndex;

  if (_array == null)

   {

       jsonWriter.WriteValue(nullPlaceholder);

       return;

   }

   jsonWriter.WriteStartArray();

   arrayItemType = _array.typeId();

   for(arrayIndex = 1; arrayIndex <= _array.lastIndex(); arrayIndex++)

   {

       if (arrayItemType == Types::Class)

       {

           this.serializeObject(_array.value(arrayIndex));

       }

       else

       {

           this.writePrimitiveValue(arrayItemType, _array.value(arrayIndex));

       }

   }

   jsonWriter.WriteEndArray();

}

private void serializeDataContract(Object _dataContract)


{


   SysDictClass dictClass;


   DataContractAttribute dataContractAttribute;


   DataMemberAttribute dataMemberAttribute;


   Set methods;


   SetEnumerator se;


   SysDictMethod dictMethod;


   str dataMemberName;


   Object dataMemberValueObject;


   container dataMemberValuePrimitive;


   container memberValues;


   anytype memberMethodReturn;


   str memberName;


   str memberMethodName;


   ExecutePermission perm;




   Map theDataContractClassMember;


   MapEnumerator theDataContractClassMemberEnumerator;


   theDataContractClassMember = new Map(Types::String, Types::AnyType);








   if (theDataContractClass == null)


   {


       theDataContractClass = new Map(Types::string, Types::AnyType);


   }




   jsonWriter.WriteStartObject();




   dictClass = new SysDictClass(classIdGet(_dataContract));




   dataContractAttribute = dictClass.getAttribute(classStr(DataContractAttribute));


   if (dataContractAttribute == null)


   {


       throw error(strFmt("@SYS134831", dictClass.name(), dictClass.id()));


   }




   perm = new ExecutePermission();


   if(perm)


   {


       perm.assert();


   }


   // check if it exists if not create it


   if (!theDataContractClass.exists(dictClass.name()))


   {


       methods = dictClass.methods(true, false, true);


       se = methods.getEnumerator();


       while (se.moveNext())


       {


           dictMethod = se.current();


           dataMemberAttribute = dictMethod.getAttribute(classStr(DataMemberAttribute));


           if (dataMemberAttribute != null)


           {


               dataMemberName = dataMemberAttribute.Name();


                if (!dataMemberName)


               {


                   dataMemberName = dictMethod.name();


               }


               memberValues = [dataMemberName, dictMethod.name(), dictMethod.returnType()];


               [ memberName, memberMethodName, memberMethodReturn] = memberValues;


               jsonWriter.WritePropertyName(memberName);




               if (memberMethodReturn == Types::Class)


               {


                   this.serializeObject(dictClass.callObject(memberMethodName, _dataContract));


               }


               else


               {


                   this.writePrimitiveValue(memberMethodReturn, dictClass.callObject(memberMethodName, _dataContract));


               }


           }


       }


 }


   CodeAccessPermission::revertAssert();




   jsonWriter.WriteEndObject();


/*


   theDataContractClassMember = theDataContractClass.lookup(dictClass.name());


   theDataContractClassMemberEnumerator = new MapEnumerator(theDataContractClassMember);


   while (theDataContractClassMemberEnumerator.moveNext())


   {

       [ memberName, memberMethodName, memberMethodReturn] = theDataContractClassMemberEnumerator.currentValue();

       jsonWriter.WritePropertyName(memberName);

       if (memberMethodReturn == Types::Class)

       {

           this.serializeObject(dictClass.callObject(memberMethodName, _dataContract));

       }

       else

       {

           this.writePrimitiveValue(memberMethodReturn, dictClass.callObject(memberMethodName, _dataContract));


       }

   }

   jsonWriter.WriteEndObject();

*/

}

private void serializeList(List _list)

{

   Types listItemType;

   ListEnumerator le;

   if (_list == null)

   {

       jsonWriter.WriteValue(nullPlaceholder);

       return;

   }

   jsonWriter.WriteStartArray();

   listItemType = _list.typeId();

   le = _list.getEnumerator();

   while (le.moveNext())

   {

       if (listItemType == Types::Class)

       {

           this.serializeObject(le.current());

      }

       else

      {

           this.writePrimitiveValue(listItemType, le.current());

       }

   }

   jsonWriter.WriteEndArray();

}

private void serializeObject(Object _object)


{


   ClassId classId;






   if (_object == null)


   {


       jsonWriter.WriteValue(nullPlaceholder);


       return;


   }




   classId = classIdGet(_object);




   switch (classId)


   {


       case classNum(List):


           this.serializeList(_object);


           break;




       case classNum(Array):


           this.serializeArray(_object);


           break;




       default:


           this.serializeDataContract(_object);


           break;


   }


}

private void writeDateTimeValue(utcDateTime _value)


{


   utcDateTime dateTimeValue;


   int64 jsDateTimeStamp;


   str jsonDateTime;






   dateTimeValue = _value;






   //jsonWriter.WriteValue(dateTimeValue);




   jsDateTimeStamp = DateTimeUtil::getDifference(dateTimeValue, dateTimeBase) * 1000;


   jsonDateTime = strFmt("\/Date(%1)\/", jsDateTimeStamp);


   jsonWriter.WriteValue(jsonDateTime);


}

private void writePrimitiveValue(Types valueType, anytype _value)


{


   str strValue;


   int intValue;


   int64 int64Value;


   real realValue;


   enumId enumId;


   boolean boolValue;


   str guidValue;


   SysDictEnum dictEnum;




   if(!nullValue(_value))


   {


       valueType = typeOf(_value);


   }




   switch (valueType)


   {


       case Types::String:


         strValue = _value;


           jsonWriter.WriteValue(strValue);


           break;




       case Types::Integer:


           intValue = _value;


           jsonWriter.WriteValue(intValue);


           break;




       case Types::Int64:


           int64Value = _value;


           jsonWriter.WriteValue(int64Value);


           break;




       case Types::Real:


           realValue = _value;


           jsonWriter.WriteValue(realValue);


           break;




       case Types::UtcDateTime:


           this.writeDateTimeValue(_value);


           break;




       case Types::Date:


           this.writeDateTimeValue(DateTimeUtil::newDateTime(_value, 0));


           break;




       case Types::Enum:


           enumId = DictEnum::value2id(_value);




           if (enumId == enumNum(boolean))


           {


               boolValue = _value;


               jsonWriter.WriteValue(boolValue);


           }


           else


           {


               dictEnum = new SysDictEnum(enumId);


               if (dictEnum != null)


               {


                   strValue = dictEnum.value2Symbol(_value);


                   jsonWriter.WriteValue(strValue);


               }


               else


               {


                   throw error(strFmt("@SYS57821", enumId));


               }


           }




           break;




       case Types::Guid:


           guidValue = guid2str(_value);


           jsonWriter.WriteValue(guidValue);


           break;




       default:


           throw error(strFmt("@SYS73815", valueType));


   }


}

private static utcdatetime dateTimeBase()


{


   return DateTimeUtil::newDateTime(1\1\1970, 0);


}

public static Object deserializeCollection(ClassId _collectionTypeId, str _serializedValue, Types _itemType, str _itemTypeName = '')


{


   System.IO.StringReader stringReader;


   Newtonsoft.Json.JsonTextReader jsonReader;


   Object deserializedCollection = null;




   stringReader = new System.IO.StringReader(_serializedValue);


   jsonReader = new Newtonsoft.Json.JsonTextReader(stringReader);


   //jsonReader.DateParseHandling = Newtonsoft.Json.DateParseHandling::None;


 jsonReader.set_DateParseHandling(Newtonsoft.Json.DateParseHandling::None);




   while(deserializedCollection == null && jsonReader.Read())


   {


       //if (jsonReader.TokenType == Newtonsoft.Json.JsonToken::StartArray)


       if (jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::StartArray)


       {


           deserializedCollection = E2C_FormJsonSerializer::deserializeCollectionInternal(_collectionTypeId, _itemType, _itemTypeName, jsonReader);


       }


   }


   return deserializedCollection;


}

private static Object deserializeCollectionInternal(ClassId _collectionTypeId, Types _itemType, str _itemTypeName, Newtonsoft.Json.JsonTextReader jsonReader)


{


   Object deserializedCollection;


   List deserializedList;


   Array deserializedArray;


   anytype deserializedItem;


   boolean continueReading;


   int itemTypeId;




   // Instantiate the desired collection type


   if(_collectionTypeId == classnum(List))


   {


       deserializedList = new List(_itemType);


       deserializedCollection = deserializedList;


   }


   else if(_collectionTypeId == classnum(Array))


   {


       deserializedArray = new Array(_itemType);


       deserializedCollection = deserializedArray;


   }




   // Resolve the item type name to the right type ID


   if(_itemType == Types::Class)


   {


       itemTypeId = className2Id(_itemTypeName);


   }


   else if(_itemType == Types::Enum)


   {


       itemTypeId = enumName2Id(_itemTypeName);


   }




   continueReading = true;


   while(continueReading && jsonReader.Read())


   {


       deserializedItem = null;


       //if (jsonReader.TokenType == Newtonsoft.Json.JsonToken::EndArray)


       if (jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::EndArray)


       {


           // Reached the end of the current array


           continueReading = false;


       }


       //else if (jsonReader.TokenType == Newtonsoft.Json.JsonToken::StartObject)


       else if (jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::StartObject)


       {


           // Deserialize the object


           deserializedItem = E2C_FormJsonSerializer::deserializeObjectInternal(itemTypeId, jsonReader);


       }


       /*


       else if (jsonReader.TokenType == Newtonsoft.Json.JsonToken::Boolean ||


           jsonReader.TokenType == Newtonsoft.Json.JsonToken::Date ||


           jsonReader.TokenType == Newtonsoft.Json.JsonToken::Float ||


           jsonReader.TokenType == Newtonsoft.Json.JsonToken::Integer ||


           jsonReader.TokenType == Newtonsoft.Json.JsonToken::String)


       */


       else if (jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::Boolean ||


           jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::Date ||


           jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::Float ||


           jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::Integer ||


           jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::String)


       {


           // Deserialize the basic type value


           //deserializedItem = SMCFormJsonSerializer::deserializeValue(_itemType, jsonReader.Value, itemTypeId);


           deserializedItem = E2C_FormJsonSerializer::deserializeValue(_itemType, jsonReader.get_Value(), itemTypeId);


       }




       // If an item was deserialized, add to the collection


       if(deserializedItem != null)


       {


           if(deserializedList)


           {


               // Add to the list


               deserializedList.addEnd(deserializedItem);


           }


           else if(deserializedArray)


            {


               // Add to the array


               deserializedArray.value(deserializedArray.lastIndex() + 1, deserializedItem);


           }


       }


   }


   return deserializedCollection;


}

public static utcdatetime deserializeDateTime(str _value)


{


   //const str dateMatchStr = '/Date(';


   int dateValueStartPos;


   int dateExpressionEndPos;


   int64 dateValueMS;


   utcdatetime parsedDate;


   #define.dateMatchStr('/Date(')




   if (strScan(_value, #dateMatchStr, 1, strLen(_value)) == 1)


   {


       dateValueStartPos = strLen(#dateMatchStr) + 1;


       dateExpressionEndPos = strScan(_value, ')', 0, strLen(_value));


       if (dateExpressionEndPos > dateValueStartPos)


       {


           dateValueMS = str2Int64(subStr(_value, dateValueStartPos, dateExpressionEndPos - dateValueStartPos));


           return DateTimeUtil::addSeconds(E2C_FormJsonSerializer::dateTimeBase(), dateValueMS div 1000);


       }


   }




   parsedDate = DateTimeUtil::parse(_value);


   return parsedDate;


}

public static Object deserializeObject(ClassId _objectTypeId, str _serializedValue)


{


   System.IO.StringReader stringReader;


   Newtonsoft.Json.JsonTextReader jsonReader;


   Object deserializedObject = null;




   stringReader = new System.IO.StringReader(_serializedValue);


   jsonReader = new Newtonsoft.Json.JsonTextReader(stringReader);


   //jsonReader.DateParseHandling = Newtonsoft.Json.DateParseHandling::None;


   jsonReader.set_DateParseHandling(Newtonsoft.Json.DateParseHandling::None);




   while(deserializedObject == null && jsonReader.Read())


   {


       //if(jsonReader.TokenType == Newtonsoft.Json.JsonToken::StartObject)


       if(jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::StartObject)


       {


           deserializedObject = E2C_FormJsonSerializer::deserializeObjectInternal(_objectTypeId, jsonReader);


       }


   }


   return deserializedObject;


}

private static Object deserializeObjectInternal(ClassId _objectTypeId, Newtonsoft.Json.JsonTextReader jsonReader)


{


   SysDictClass objectType = new SysDictClass(_objectTypeId);


   Set objectMethods;


   SysDictMethod objectMethod;


   SetEnumerator se;


   str currentJsonProperty;


   str dataMemberName;


   anytype propertyValue;


   DataMemberAttribute memberAttribute;


   //DataCollectionAttribute collectionAttribute;


   E2C_DataCollectionAttribute collectionAttribute;


   Map dataMembers = new Map(Types::String, Types::Class);


   Object deserializedObject = objectType.makeObject();


   boolean continueReading;


   Types returnType;


   enumId enumId;


   DictType dt;




   // Find all valid data members on this type


   objectMethods = objectType.methods(true, false, true);


   se = objectMethods.getEnumerator();


   while (se.moveNext())


   {


       objectMethod = se.current();


       memberAttribute = objectMethod.getAttribute(classStr(DataMemberAttribute));


       if (memberAttribute != null)


       {


           dataMemberName = memberAttribute.Name();


           if (!dataMemberName)


           {


               dataMemberName = objectMethod.name();


           }


           dataMembers.insert(dataMemberName, objectMethod);


       }


   }




   continueReading = true;


   while(continueReading && jsonReader.Read())


   {


       //if (jsonReader.TokenType == Newtonsoft.Json.JsonToken::EndObject)


       if (jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::EndObject)


       {


           // Reached the end of the current object


           continueReading = false;


       }


       //else if (jsonReader.TokenType == Newtonsoft.Json.JsonToken::PropertyName)


       else if (jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::PropertyName)


       {


          // This is identifying a property


           //currentJsonProperty = jsonReader.Value;


           currentJsonProperty = jsonReader.get_Value();


       }


       //else if (jsonReader.TokenType == Newtonsoft.Json.JsonToken::StartArray)


       else if (jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::StartArray)


       {


           // This is the case for collection type properties


           if(currentJsonProperty)


           {


               if(dataMembers.exists(currentJsonProperty))


               {


                   // Determine if the property has a colleciton attribute


                   objectMethod = dataMembers.lookup(currentJsonProperty);


                   collectionAttribute = objectMethod.getAttribute(classStr(E2C_DataCollectionAttribute));


                   if(collectionAttribute)


                   {


                       // Deserialize the collection


                       propertyValue = E2C_FormJsonSerializer::deserializeCollectionInternal(


                            objectMethod.returnId(),


                           collectionAttribute.itemType(),


                           collectionAttribute.itemTypeName(),


                           jsonReader);


                       // Set the property


                        objectType.callObject(objectMethod.name(), deserializedObject, propertyValue);


                   }


               }


           }


       }


       //else if (jsonReader.TokenType == Newtonsoft.Json.JsonToken::StartObject)


       else if (jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::StartObject)


       {


           // This is the case for nested complex type properties


           if(currentJsonProperty)


           {


               if(dataMembers.exists(currentJsonProperty))


                {


                   // Read the object from JSON


                   objectMethod = dataMembers.lookup(currentJsonProperty);


                   // Desrialize the object property


                   propertyValue = E2C_FormJsonSerializer::deserializeObjectInternal(objectMethod.returnId(), jsonReader);


                   // Set the proeprty value


                   objectType.callObject(objectMethod.name(), deserializedObject, propertyValue);


               }


           }


       }


       /*


       else if (jsonReader.TokenType == Newtonsoft.Json.JsonToken::Boolean ||


           jsonReader.TokenType == Newtonsoft.Json.JsonToken::Date ||


           jsonReader.TokenType == Newtonsoft.Json.JsonToken::Float ||


           jsonReader.TokenType == Newtonsoft.Json.JsonToken::Integer ||


           jsonReader.TokenType == Newtonsoft.Json.JsonToken::String)


       */


       else if (jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::Boolean ||


           jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::Date ||


           jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::Float ||


           jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::Integer ||


           jsonReader.get_TokenType() == Newtonsoft.Json.JsonToken::String)


       {


           // This is the case for basic type values


           //if(jsonReader.Value && deserializedObject && currentJsonProperty)


           if(jsonReader.get_Value() && deserializedObject && currentJsonProperty)


          {


               if(dataMembers.exists(currentJsonProperty))


               {


                   objectMethod = dataMembers.lookup(currentJsonProperty);


                   //Types returnType = objectMethod.returnType();


                  returnType = objectMethod.returnType();


                   //enumId enumId = objectMethod.returnId();


                   enumId = objectMethod.returnId();


                   if (returnType == Types::UserType)


                   {


                      // Get the base type for extended data type


                       returnType = extendedTypeId2Type(objectMethod.returnId());


                       if (returnType == Types::Enum)


                       {


                           // Get the enumId for enum EDT types


                           //DictType dt = new DictType(objectMethod.returnId());


                           enumId = dt.enumId();


                       }


                   }


                   // Deserialize primitive value


                 propertyValue = E2C_FormJsonSerializer::deserializeValue(


                       returnType,


                       //jsonReader.Value,


                       jsonReader.get_Value(),


                       enumId);


                   // Set the property value


                   objectType.callObject(objectMethod.name(), deserializedObject, propertyValue);


               }


           }


       }




   }


   return deserializedObject;


}

public static anytype deserializeValue(Types _type, str _value, enumId _enum = 0)


{


   anytype typedValue = null;


   int64 int64value;


   int intvalue;


   real realvalue;




   switch (_type)


   {


       case Types::Date:


           {


               //iso date format to x++ date format


               typedValue = str2Date(_value, 321); break;


           }


       case Types::Enum: typedValue = symbol2Enum(_enum, _value); break;


       case Types::Guid: typedValue = str2Guid(_value); break;


       case Types::Int64:


           {


               //int64 int64value = System.Int64::Parse(_value, System.Globalization.CultureInfo::InvariantCulture);


               int64value = System.Int64::Parse(_value, System.Globalization.CultureInfo::get_InvariantCulture());


               typedValue = int64value;


               break;


           }


       case Types::Integer:


           {


               //int intvalue = System.Int32::Parse(_value, System.Globalization.CultureInfo::InvariantCulture);


               intvalue = System.Int32::Parse(_value, System.Globalization.CultureInfo::get_InvariantCulture());


               typedValue = intvalue;


                break;


           }


       case Types::Real:


           {


               //real realvalue = System.Decimal::Parse(_value, System.Globalization.CultureInfo::InvariantCulture);


               realvalue = System.Decimal::Parse(_value, System.Globalization.CultureInfo::get_InvariantCulture());


               typedValue = realvalue;


               break;


           }


       case Types::String: typedValue = _value; break;


       case Types::VarString: typedValue = _value; break;


       case Types::Time: typedValue = str2time(_value); break;


       case Types::UtcDateTime: typedValue = E2C_FormJsonSerializer::deserializeDateTime(_value); break;


       default:


           // Any other kind of type is illegal for setting


           throw error("The type of object cannot be set.");


   }




   return typedValue;


}

public static str normalizeNameForJSON(str inputString)


{


   // this function must sync with NormalizeNameForJSON in %INETROOT%\Source\Kernel\Source\FormDataSourceInteraction.cpp


   int pos = strfind(inputString, '[', 1, strlen(inputString));


   if(pos > 0)


   {


       inputString = strDel(inputString, pos, 1);


       inputString = strIns(inputString, '_', pos);




       pos = strfind(inputString, ']', 1, strlen(inputString));


       if(pos > 0)


       {


           inputString = strDel(inputString, pos, 1);


       }


   }


   pos = strfind(inputString, ' ', 1, strlen(inputString));


   if(pos > 0)


   {


       inputString = strDel(inputString, pos, 1); // remove spaces in fieldname since they cause serialization error


   }




   return inputString;


}

public static str serializeClass(Object _object)


{


   E2C_FormJsonSerializer serializer;




   if (_object == null)


   {


       return 'null';


   }




   serializer = new E2C_FormJsonSerializer();


   serializer.serializeObject(_object);




   return serializer.json();


}

public static str serializePrimitive(anytype propertyValue, enumId _enum = 0)


{


   Types valueType;


   System.String strValue;


   System.Int32 intValue;


   System.Int64 int64Value;


   System.Decimal realValue;


   if(propertyValue != null)


   {


       valueType = typeOf(propertyValue);


   }




   switch (valueType)


   {


       case Types::Integer:


           intValue = propertyValue;


           //strValue = intValue.ToString(System.Globalization.CultureInfo::InvariantCulture);


           strValue = intValue.ToString(System.Globalization.CultureInfo::get_InvariantCulture());


           return strValue;




       case Types::Int64:


           int64Value = propertyValue;


           //strValue = int64Value.ToString(System.Globalization.CultureInfo::InvariantCulture);


           strValue = int64Value.ToString(System.Globalization.CultureInfo::get_InvariantCulture());


           return strValue;




       case Types::Real:


           realValue = propertyValue;


           //strValue = realValue.ToString(System.Globalization.CultureInfo::InvariantCulture);


           strValue = realValue.ToString(System.Globalization.CultureInfo::get_InvariantCulture());


           return strValue;




       case Types::Time:


           // x++ timeOfDay


           int64Value = propertyValue;


           //strValue = int64Value.ToString(System.Globalization.CultureInfo::InvariantCulture);


           strValue = int64Value.ToString(System.Globalization.CultureInfo::get_InvariantCulture());


           return strValue;




       case Types::UtcDateTime:


           //x++ utcdatetime format yyyy-mm-ddThh:mm:ss to iso datetime format


          return DateTimeUtil::toStr(propertyValue);




       case Types::Date:


           //x++ date format to iso date format yyyy-mm-dd


           strValue = date2str(propertyValue,321,DateDay::Digits2,DateSeparator::Hyphen,DateMonth::Digits2,DateSeparator::Hyphen,DateYear::Digits4);


           return strValue;




       case Types::Enum:


           if (_enum)


           {


               return enum2Symbol(_enum, propertyValue);


           }


           else


           {


               return strFmt('%1', propertyValue);


           }




       default:


           return strFmt('%1', propertyValue);


   }




}