I am trying to serialize some JSON input to a data contract in Microsoft Dynamics 365 Finance. A simple data contract class works fine, but I cannot get data contract extensions to work. Does any one have experience with this or perhaps a working example?
The only related information I managed to find on this topic comes from this forum post. Follow some hyperlinks and you will end up with the official Microsoft documentation (Ref# 199219), which states that this should be supported.
All variations of the data contract attributes below compile fine, but proved unsuccessful for me:
- Using
DataContract
andDataMember
instead ofDataContractAttribute
andDataMemberAttribute
. - Combining
DataContract
andDataContractAttribute
on a single method. (Produces runtime error about double serialization attribute.) - Repeating the
DataContractAttribute
on the extension class.
Additional experiments with the JSON deserializer class through its various constructor options also proved unsuccessful:
- Passing a list of known types
ClassA
andClassA_Extension
. - Passing a list of known types
ClassA_Extension
andClassA
(in case the list order had an impact). - Passing a settings object and explicitly setting
IgnoreExtensionDataObject
tofalse
(this appears to be the default). - Passing the extension class type as first parameter.
Update
A ticket was raised with Microsoft to investigate the issue. In their response they mentioned that they were able to reproduce this. They also declared that this was "by design" and "will not be fixed".
Our final solution will most likely be the following:
- Build a mapping of
DataMemberAttribute
values and the corresponding data contract method. - Use a
JavaScriptSerializer
object to turn the JSON into a nested .NET dictionary object. - Iterate over the dictionary object and populate the data contract with the help of the mapping.
Example
Below is a miminal example to demonstrate my issue. The values of the variables value1
and value2
are populated as expected, but variable value3
remains empty.
Data contract
[DataContractAttribute('Class A')]
public class ClassA
{
protected str value1;
protected str value2;
[DataMemberAttribute('Value1')]
public str value1(str _value1 = value1)
{
value1 = _value1;
return value1;
}
[DataMemberAttribute('Value2')]
public str value2(str _value2 = value2)
{
value2 = _value2;
return value2;
}
}
Data contract extension
[ExtensionOf(classStr(ClassA))]
public final class ClassA_Extension
{
private str value3;
[DataMemberAttribute('Value3')]
public str value3(str _value3 = value3)
{
value3 = _value3;
return value3;
}
}
Serialization code with hard-coded input
public class ClassTest
{
public static void main(Args _args)
{
str inputJSON = @'{
"Value1": "abc",
"Value2": "def",
"Value3": "ghi"
}';
ClassA ret = new ClassA();
System.IO.MemoryStream ms = new System.IO.MemoryStream(System.Text.Encoding::UTF8.GetBytes(inputJSON));
System.Runtime.Serialization.Json.DataContractJsonSerializer dcjSer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(ret.GetType());
ret = dcjSer.ReadObject(ms);
ms.Close();
}
}
Result