Tuesday, October 22, 2019

Deserializing Json Array in D365

I was experiencing an issue while creating a purchase requisition which has more than single line in D365  environment via service. The issue was actually specific to de-serializing the JSON array D365 (X++).  Here I am sharing with you the code which may be helpful for you.


   "purchaseRequisitionList":{ 
      "PurchaseRequisition":[ 
         { 
            "ItemId":"Item1",
            "ItemQty":3
  },
         { 
            "ItemId":"Item2",
            "ItemQty":2
         }
      ]
   }
}

First thing let's create data contracts similar to json above, where would define list for JSON  array.

[DataContract]
class PurchaseRequisitionList
{
    List purchaseRequistion;

    [DataMember("PurchaseRequisition")]

    public List parmLinesDetail(List _purchaseRequistion = purchaseRequistion)
    {
        purchaseRequistion = _purchaseRequistion;
        return purchaseRequistion;
    }

}


[DataContract]
class CreatePurchaseRequisitionContract

    ItemId                   itemId;
    Qty                      itemQty;


    [DataMember("ItemId")]

    public ItemId parmItemId(ItemId _itemId = itemId)
    {
        itemId = _itemId;
        return itemId;
    }

    [DataMember("ItemQty")]

    public Qty parmItemQty(Qty _itemQty = itemQty)
    {
        itemQty = _itemQty;
        return itemQty;
    }
}


It was the issue relating to de serializing of JSON array to our contract class. Add the following code to utilize the newtosoft for JObject.

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Given below is the code for posting the purchase requisition. You can add exception handling and fields the way you like.

public EntityResponseContract PostPurchaseRequisitionNew(PurchaseRequisitionList purchaseRequisitionList)
{
  EntityResponseContract      response = new EntityResponseContract();
  str                         message;
  boolean                     success = false;
  PurchReqTable               purchReq;
  PurchReqLine                purchReqLine;


purchReq.clear();
purchReq.initValue();

purchReq.PurchReqId              = NumberSeq::newGetNum(PurchReqTable::numRefPurchReqId()).num();

purchReq.insert();

ListIterator linesDetailIterator = new ListIterator(purchaseRequisitionList.parmLinesDetail());


while(linesDetailIterator.more())

{
JObject headerJObject = linesDetailIterator.value();
purchaseRequisition = JsonParser::JsonToObject(classStr(CreatePurchaseRequisitionContract), headerJObject.ToString());

ttsbegin;

purchReqLine.clear();
purchReqLine.initValue();
purchReqLine.initFromPurchReqTable(purchReq);
purchReqLine.Name                   = purchaseRequisition.parmItemId();
purchReqLine.PurchQty               = purchaseRequisition.parmItemQty();
/*All your remaining fields you can place here*/
purchReqLine.insert();
ttscommit;

linesDetailIterator.next();

}
}

You can write a new class call it JsonParser, or simply type this method is class above.

public class JsonParser
{
//This method will deserialize the json to object
public static object JsontoObject(str _className,str _json)
    {
        Object      returnObject=null;
        try
        {
            returnObject= FormJsonSerializer::deserializeObject(className2Id(_className),_json);
        }
        catch
        {
            error("Unable to deserialize due to an error");
        }
        return returnObject;
    }
}

I hope that will also be a quick start for service end point.