Monday, 6 October 2025

D365FO JSON serialization and deserialization

 Contract classes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
[DataContractAttribute('MainContract')]
class VKMainContract
{
    protected str                    status;
    protected VKAdditionalContact    additionalContract;
    protected List                    subList;
 
     
    [DataMemberAttribute("Status")]
    public str parmStatus(str _status = status)
    {
        status = _status;
        return status;
    }
 
    [DataMemberAttribute("AdditionalContract")]
    public VKAdditionalContact parmAdditionalContract(VKAdditionalContact _additionalContract = additionalContract)
    {
        additionalContract = _additionalContract;
        return additionalContract;
    }
 
    [DataMemberAttribute("ContractList"),
        DataCollectionAttribute(Types::Class, classStr(VKThirdContract))]
    public List parmSubList(List _subList = subList)
    {
        subList = _subList;
        return subList;
    }
}
[DataContractAttribute("AdditionalContact")]
class VKAdditionalContact
{
    protected str field;
 
    [DataMemberAttribute("SomeAdditionalField")]
    public str parmSomeAdditionalField(str _field = field)
    {
        field = _field;
        return field;
    }
 
}
[DataContractAttribute('ThirdContract')]
class VKThirdContract
{
    protected str    field1;
    protected str    field2;
 
    [DataMemberAttribute("SomeField1")]
    public str parmSomeField1(str _field = field1)
    {
        field1 = _field;
        return field1;
    }
 
    [DataMemberAttribute("SomeField2")]
    public str parmSomeField2(str _field = field2)
    {
        field2 = _field;
        return field2;
    }
 
}
JSON example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[
   {
      "AdditionalContract":{
         "SomeAdditionalField":"test1"
      },
      "ContractList":[
         {
            "SomeField1":"field1",
            "SomeField2":"field2"
         },
         {
            "SomeField1":"field1",
            "SomeField2":"field2"
         }
      ],
      "Status":"status1"
   },
   {
      "AdditionalContract":{
         "SomeAdditionalField":"test2"
      },
      "ContractList":[
         {
            "SomeField1":"field1",
            "SomeField2":"field2"
         },
         {
            "SomeField1":"field1",
            "SomeField2":"field2"
         }
      ],
      "Status":"status2"
   }
]
Runnable class to serialize contracts to JSON and then deserialize JSON back to same contracts:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class VKTest
{
    public static void main(Args _args)
    {
        VKAdditionalContact    additionalContact    = new VKAdditionalContact();
        VKMainContract        mainContract        = new VKMainContract();
        VKThirdContract        thirdContract        = new VKThirdContract();
        List                itemMainList        = new List(Types::Class);
        List                itemThirdList        = new List(Types::Class);
 
        thirdContract.parmSomeField1('field1');
        thirdContract.parmSomeField2('field2');
        itemThirdList.addEnd(thirdContract);
        itemThirdList.addEnd(thirdContract);
 
        additionalContact.parmSomeAdditionalField('test1');
         
        mainContract.parmAdditionalContract(additionalContact);
        mainContract.parmStatus('status1');
        mainContract.parmSubList(itemThirdList);
 
        itemMainList.addEnd(mainContract);
 
        mainContract        = new VKMainContract();
        additionalContact    = new VKAdditionalContact();
        additionalContact.parmSomeAdditionalField('test2');
        mainContract.parmStatus('status2');
        mainContract.parmAdditionalContract(additionalContact);
        mainContract.parmSubList(itemThirdList);
        itemMainList.addEnd(mainContract);
 
        // case 1: json starts from array []
        str json = FormJsonSerializer::serializeClass(itemMainList);
        // case 2: json starts from object {}
        //str json = FormJsonSerializer::serializeClass(mainContract);
        info(json);
 
        itemMainList        = new List(Types::Class);
        itemThirdList        = new List(Types::Class);
        mainContract        = new VKMainContract();
        additionalContact    = new VKAdditionalContact();
        thirdContract        = new VKThirdContract();
        ListEnumerator     leSub;
 
        // case 1
        itemMainList = FormJsonSerializer::deserializeCollection(classnum(List), json, Types::Class, identifierStr('VKMainContract'));
        ListEnumerator     le = itemMainList.getEnumerator();
        while (le.moveNext())
        {
            mainContract        = le.current();
            additionalContact    = mainContract.parmAdditionalContract();
            itemThirdList        = mainContract.parmSubList();
            leSub                = itemThirdList.getEnumerator();
            while (leSub.moveNext())
            {
                thirdContract = leSub.current();
            }
        }
 
        // case 2
        /*mainContract = FormJsonSerializer::deserializeObject(classNum(VKMainContract), json);
        additionalContact    = mainContract.parmAdditionalContract();
        itemThirdList        = mainContract.parmSubList();
        leSub                = itemThirdList.getEnumerator();
        while (leSub.moveNext())
        {
            thirdContract = leSub.current();
        }*/
 
        info("done");
    }
 
}
JSON does not have to completely match the contract. In that case only matching properties will be filled in. That is valid only for simple types like string and integer, for objects and arrays at least empty contract class and parm method should be in place. Otherwise you might get following error: " the type of object cannot be set."
1
2
    json = '{"SomeField1":"field1","SomeAdditionalField":"field2"}';
    thirdContract = FormJsonSerializer::deserializeObject(classNum(VKThirdContract), json);
In case of simple JSON structure Map can be used to get values
1
2
3
4
    json = '{"SomeField1":"field1","SomeAdditionalField":"field2"}';
    Map            responseMap = RetailCommonWebAPI::getMapFromJsonString(json);
    container    con            = responseMap.lookup('SomeField1');
    str            value        = conPeek(con, 1);
D365 F&SCM date format: 2024-05-27T00:00:00Z
FormJsonSerializer.writeDateTimeValue

No comments:

Post a Comment

Creating new D365FO Business Event

  The name should include the noun or phrase that corresponds with theevent, followed by the BusinessEvent suffix. New business event for Cu...