Taking JSON input with D365 service and deserialize into contract objects

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.

Comments

  1. 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.
    [
    DataMemberAttribute("Student list"),
    AifCollectionTypeAttribute("return", Types::Class, classStr(StudentInfoContract)),
    AifCollectionTypeAttribute("_studentList", Types::Class, classStr(StudentInfoContract))
    ]
    public List parmStudentList(List _studentList = studentList)

    ReplyDelete

Post a Comment