Recently I wanted to create a custom serivce in D365 taking in a JSON input. I did my usual google search but ended up needing additional trial and error to complete the use case. Here I'll share the solution I have..
Firstly, create a contract class which represent the a Json object
/// <summary> /// The Student Information object contains the Student ID and Name /// </summary> [DataContractAttribute] class StudentInfoContract { str studentId; str studentName; [DataMemberAttribute("Student Id")] public str parmStudentId(str _studentId = studentId) { studentId = _studentId; return studentId; } [DataMemberAttribute("Student Name")] public str parmStudentName(str _studentName = studentName) { studentName = _studentName; return studentName; } }
Then, in the service contract class, define a List of Str which will take in the Json
/// <summary> /// Contains a list of students /// </summary> [DataContractAttribute] class StudentsContract { List studentList = new List(Types::String); [ DataMemberAttribute("Student list"), DataCollectionAttribute(Types::Class, classStr(StudentInfoContract)) ] public List parmStudentList(List _studentList = studentList) { if (!prmIsDefault(_studentList)) { studentList = _studentList; } return studentList; } }
At run time, when calling code provides a list of Json objects, it'll be come a list of JObjects in X++. We'll loop through the list and use FormDeserializer to deserialize each JObject into a contract instance
List studentList = StudentsContract.parmStudentList(); ListEnumerator enumerator = studentList.getEnumerator(); while (enumerator.moveNext()) { Newtonsoft.Json.Linq.JObject jObj = enumerator.current(); studentInfoContract = FormJsonSerializer::deserializeObject(classNum(StudentInfoContract),jObj.ToString()); str studentId, studentName; studentId = studentInfoContract.parmStudentId(); studentName = studentInfoContract.parmStudentName(); Info(strFmt("Studnet # %1: %2", studentId, studentName)); }
In the end it's quite simple, and also no need to create C# class representing the data contract as well.
This posting is provided "AS IS" with no warranties, and confers no rights.
It's like you try to do a sunset manually. DataCollectionAttribute is mostly for forms (that's why FormJsonSerializer knows about it), and in custom services just use good old AifCollectionTypeAttribute for "return" and for "_studentList" (your parameter) - and you'll get your collection deserialized by the platform.
ReplyDelete[
DataMemberAttribute("Student list"),
AifCollectionTypeAttribute("return", Types::Class, classStr(StudentInfoContract)),
AifCollectionTypeAttribute("_studentList", Types::Class, classStr(StudentInfoContract))
]
public List parmStudentList(List _studentList = studentList)