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.
I have checked that out, and for json like following:
ReplyDelete{
"success": true,
"data": [
{
"CUST_GROUP_ID": 1,
"CUST_GROUP_NAME": "Customer Group 1",
"INSERT_FLAG": "Y",
"RECORD_SENT_FLAG": "N",
"ERROR_MESSAGE": null,
"LAST_UPDATE_DATE": "2020-03-01T13:29:29.000Z",
"LAST_UPDATED_BY": 0,
"CREATION_DATE": "2020-03-01T13:29:29.000Z",
"CREATED_BY": 0
},
{
"CUST_GROUP_ID": 2,
"CUST_GROUP_NAME": "Customer Group 2",
"INSERT_FLAG": "Y",
"RECORD_SENT_FLAG": "N",
"ERROR_MESSAGE": null,
"LAST_UPDATE_DATE": "2020-03-01T13:29:29.000Z",
"LAST_UPDATED_BY": 0,
"CREATION_DATE": "2020-03-01T13:29:29.000Z",
"CREATED_BY": 0
}
]
}
I am trying to create a job with below code
.
RetailWebRequest request;
RetailWebResponse response;
str rawResponse;
RetailCommonWebAPI webApi;
System.IO.Stream requestStream, responseStream;
System.IO.StreamReader reader;
Object deserializedContract;
List list;
ListIterator listIterator;
CreateCustGroupContract custGroupContract;
CustGroupList custGroupList;
webApi = RetailCommonWebAPI::construct();
request = RetailWebRequest::newUrl("URL");
response = webApi.getResponse(request);
rawResponse = response.parmData();
custGroupList = new CustGroupList();
listIterator = new ListIterator(custGroupList.parmDataDetail());
while (listIterator.more())
{
custGroupContract = SMCFormJsonSerializer::deserializeObject(classIdGet(custGroupContract), listIterator.value());
info(strFmt('%1', custGroupContract.parmCustGroupId()));
info(custGroupContract.parmCustGroupName());
listIterator.next();
}
but its only return "CUST_GROUP_ID": 1, "CUST_GROUP_NAME": "Customer Group 1".
How can we achieve all the json string like "CUST_GROUP_ID": 1, "CUST_GROUP_NAME": "Customer Group 1", "CUST_GROUP_ID": 2, "CUST_GROUP_NAME": "Customer Group 2".
Can you please help me to achieve the requirement.
Thanks,
Somesh
Thanks for sharing useful information.. we have learned so much information from your blog....
ReplyDeleteMicrosoft Dynamics AX Technical Training in Hyderabad
MS Dynamics Technical Online Training
MS Dynamics AX Technical Training in Hyderabad
MS Dynamics AX Online Training
D365 AX Online Training