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;
}
}
{
"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.