Skip to main content

Notifications

Dynamics 365 Community / Forums / Finance forum / Serialize X++ objects ...
Finance forum

Serialize X++ objects to JSON

Posted on by Microsoft Employee

I want to use RestAPI from D365. We tried following approached
• Use newtonsoft Dll.
• Use “FormJsonSerializer“ class
And we are facing the following issue
• Unable to serialize and deserialize objects using newtonsoft dll. Always return blank object.
• We are able to serialize and deserialize object using FormJsonSerializer but if rest call contains multiple List objects then its throwing error.

  • Suggested answer
    vinaysahu Profile Picture
    vinaysahu 2 on at
    Serialize X++ objects to JSON
    There are two scenarios in which we may desire to serialize a class:
    1. When the class comprises primitive variables.
    2. When the class includes a list (collection) of elements.
     
    Lets take first scenerio:
    Class should be like this:
    [DataContract]
    public final class ExUnattachedReceipt
    {
        private Description name;
        private int amount;
        private str createdDate;
     
        [DataMember('name')]
        public str parmName(str _name = name)
        {
            name = _name;
            return name;
        }
     
        [DataMember('amount')]
        public int parmAmount(int _amount = amount)
        {
            amount = _amount;
            return amount;
        }
     
        [DataMember('createdDate')]
        public str parmCreatedDate(str _createdDate = createdDate)
        {
            createdDate = _createdDate;
            return createdDate;
        }
    }

    We can directly call FormJsonSerializer::serializeClass(ExUnattachedReceipt);

    -------------------------------------------------------------------------------------------------------------------------------------------------------------

    Now lets take their another scenerio where above class is added as Collection and we want to serialize outer class

     

    [DataContract]
    public final class ExUnattachedReceiptList
    {
        private List exReceipts = new List(Types::Class);
     
        [DataMember('exReceipts'),
            DataCollection(Types::Class, classStr(ExUnattachedReceipt))]

        public List parmExReceipts(List _exReceipts = exReceipts)
        {
            exReceipts = _exReceipts;
            return exReceipts;
        }
    }

     
    We can directly call FormJsonSerializer::serializeClass(ExUnattachedReceiptList);
  • Suggested answer
    Mat Fergusson Profile Picture
    Mat Fergusson 7 on at
    RE: Serialize X++ objects to JSON

    In case anyone finds this. The output is empty because Newtonsoft is deliberately ignoring your data members.

    The x compiler takes each DataMember attribute and makes a dotnet property out of it. That property is marked as "compiler generated", and Json.net will ignore compiler generated properties by default.

    So, to serialise/deserialise an x object you have to tell Json.net to include compiler generated properties.

    eg.

        public static str Serialise(Object _obj)
        {
            Newtonsoft.Json.Serialization.DefaultContractResolver resolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
            resolver.SerializeCompilerGeneratedMembers = true;
    
            Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings();
            settings.ContractResolver = resolver;
    
            return Newtonsoft.Json.JsonConvert::SerializeObject(_obj, settings);
        }

  • 0993BV Profile Picture
    0993BV on at
    RE: Serialize X++ objects to JSON

    After trying to figure out why JSONConvert doesnt work for the last 4 hours, I ended up doing the above suggestion. Thanks a ton! Not sure why I couldnt see this in my search earlier, but definitely a saviour.

  • Suggested answer
    M.K. Profile Picture
    M.K. 10 on at
    RE: Serialize X++ objects to JSON

    This should work:

    str formatedJSON = JsonConvert::SerializeObject(JsonConvert::DeserializeObject(FormJsonSerializer::serializeClass(object)), Formatting::Indented);

  • Shaik146 Profile Picture
    Shaik146 932 on at
    RE: Serialize X++ objects to JSON

    Hi sohail,

    can you send your solution /way of approach.?  i hav similar requirement.

  • Suggested answer
    Martin Dráb Profile Picture
    Martin Dráb 229,275 Most Valuable Professional on at
    RE: RestAPI from D365
    I can confirm that directly using JsonConvert::SerializeObject() doesn't work for me with normal X++ objects. I didn't investigate why; a simple workaround is defining the class in C# and using properties. Your Product class could look like this:
    public class Product
    {
        public string Id { get; set; }
        public str Name { get; set; }
    }
    (This is even shorter than your original code.)
    Then you can use create an instance in X++, fill it with data and pass it to JsonConvert::SerializeObject() in X++. Like this:
    YourCSharpLib.Product product = new YourCSharpLib.Product();
    product.Id = "1";
    product.Name = "Test";
    
    str json = Newtonsoft.Json.JsonConvert::SerializeObject(product, Newtonsoft.Json.Formatting::Indented);
    By the way, it's now clear that the problem isn't related to Rest API, therefore let me change the title from "RestAPI from D365" to something more fitting.
  • Suggested answer
    Sasha Dudarenko Profile Picture
    Sasha Dudarenko 50 on at
    RE: RestAPI from D365

    Show us please inbound JSON message.

    If your message contain a list of your datacontracts (DC), then you have to wrap AX DC to another DC, like:

    [DataContractAttribute]
    class DataContractClass
    {
        DataAreaId dataAreaId;
        List subContractList;
    
        [DataMemberAttribute('DataAreaId')]
        public Description parmDataAreaId(DataAreaId _dataAreaId = dataAreaId)
        {
            dataAreaId = _dataAreaId;
            return dataAreaId;
        }
    
        [DataMemberAttribute('SubContractList'),
            AifCollectionTypeAttribute('_subContractList', Types::Class, classStr(SubContractDataContract))]
        public List parmSubContractList(List _subContractList = subContractList)
        {
            subContractList = _subContractList;
            return subContractList;
        }
    
    }



    ====

    To serialize/deserialize DC use:

    DataContractClass dataContract = new DataContractClass();
    
    dataContract.parmDataAreaId('ABCD');
    
    List subContractDCList = new List(Types::Class);
    SubContractDataContract subContractDC = new SubContractDataContract();
    subContractDC.parmCustomerAccount('ABCD-000001');
    
    subContractDCList.addEnd(subContractDC);
    dataContract.parmProjContractList(subContractDCList);
    
    //serialize DC -> JSON
    str jsonSerializedContract = FormJsonSerializer::serializeClass(dataContract);
    
    //deserialize JSON -> DC
    Object deserializedDc = FormJsonSerializer::deserializeObject(classIdGet(dataContract), jsonSerializedContract);
    List deserializedSubDcList = deserializedDc.parmSubContractList();
    if (deserializedSubDcList)
    {
        ListEnumerator le_DeserializedSubDc = deserializedSubDcList.getEnumerator();
        while (le_DeserializedSubDc.moveNext())
        {
            SubContractDataContract deserializedSubDc = le_DeserializedSubDc.current();
            //Actions with subDC
        }
    }
  • Sheikh Sohail Profile Picture
    Sheikh Sohail 6,125 on at
    RE: RestAPI from D365

    Hi

    There is another easy way to handle your case.. if you can consume web service from C# client and only get response on D365.

    We have the same requirement previously in one of our project. To achieve this We created everything in C#  project even the attribute classes and consume the services as well with in C#.

    Then add the reference of the C# project  DLLs in D365FO and call the method to consume the service. even all type of serialization we were performing on C# end.

    If you are still facing any issue do let me know we can discuss this in detail.

  • Jie G Profile Picture
    Jie G on at
    RE: RestAPI from D365

    It should be nothing with D365. You can debug into the newtonsoft.dll to see why the method returns empty string.

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: RestAPI from D365

    We have created the Class as

    [DataContractAttribute]

    public class Product

    {

      private str id1;

      Private str name1;

      [DataMemberAttribute]

      public str id(str _id=id1)

      {

          id1 = _id;

          return id1;

      }

      [DataMemberAttribute]

      public str name(str _name=name1)

      {

          name1 = _name;

          return name1;

      }

    }

    Create on runnable call and added following code

    Str json;

    product = new Product();

    product.id("1");

    product.name("Test");

    json = Newtonsoft.Json.JsonConvert::SerializeObject(product,Newtonsoft.Json.Formatting::Indented);

    info (json);

    Newton soft always return blank Json string.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

November Spotlight Star - Khushbu Rajvi

Congratulations to a top community star!

Forum Structure Changes Coming on 11/8!

In our never-ending quest to help the Dynamics 365 Community members get answers faster …

Dynamics 365 Community Platform update – Oct 28

Welcome to the next edition of the Community Platform Update. This is a status …

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 290,900 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 229,275 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans